digitalpetri / modbus

Modbus TCP, Modbus RTU/TCP, and Modbus RTU/Serial for Java 17+.
Eclipse Public License 2.0
653 stars 222 forks source link

Threading problems #29

Closed thhart closed 4 years ago

thhart commented 4 years ago

We are polling a modbus system with very high frequency. We are facing problems that there are major delays when new threads are spawned for every read request and the system is very busy with other threads. Is there a way to have the calls running in a specific thread without spawning? We are aware this might conflict with the whole design.

ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder(ioParameter.getAddress())
                        .setPort(ioParameter.getPort()).setTimeout(Duration.ofSeconds(2))
                        .build();
                modbusClient = new ModbusTcpMaster(config);
                modbusClient.connect();

      CompletableFuture future = modbusClient.sendRequest(new ReadDiscreteInputsRequest(0, 8), 0);
      ^^^^^ Thread is spawned and execution is not guaranteed ^^^^^

Version: 1.1.1

kevinherron commented 4 years ago

Calling sendRequest doesn't spawn a new thread, but it does leave you with an unanswered CompleteableFuture that will eventually be completed by a different thread.

It sounds like you need to implement some kind of queue mechanism in your system that you submit requests to and it provides some kind of guarantees that only N requests at a time will be executing, i.e. until there are less than N currently executing requests to finish before executing polling and executing new ones.

However I can't tell from your description if your problem is that: 1) you have a set of requests that you execute repeatedly without actually waiting for the previous set to finish 2) the device you're connected to has issues with the level of parallelism you're issuing requests 3) both

kevinherron commented 4 years ago

Also, if you're not already aware, you can turn this into a synchronous call just by immediately calling get() on the CompleteableFuture from sendRequest.

thhart commented 4 years ago

Thanks for the the fast helpful answers. My problem is following: I want to make sure I can poll a Slave with very high frequency with as low as possible delay. I am speaking of 250 Hz. On top of this the Master is a Java system which must do a lot of parallel processing things simultaneously (spawning threads and so on not related to the Modbus part). Yes, you are right what I want to achieve is a synchronous system making sure the Slave will be polled sequentially as best as possible regardless how busy the system is (threading wise). So taking your advice I could check following which would not create any threads:

private int sendRead(ReadDiscreteInputsRequest input) throws Exception {
      CompletableFuture future = modbusClient.sendRequest(input, 0);
      ReadDiscreteInputsResponse response = null;
      try {
         response = future.get();
         return response.getInputStatus().readUnsignedByte();
      } finally {
         if(response != null) {
            ReferenceCountUtil.release(response);
         }
      }
}
thhart commented 4 years ago

I have tested and it looks performing ok. Thanks for suggestions again.