Modbus binding v2 much slower, making habpanel unusable

I finally got the time to sit down and migrate my modbus 1.0 binding config (~100 items) to the new v2 binding format. Got everything migrated and stuff is polling properly. However the speed in which items update is incredibly slow compared to the old v1 binding - to the point buttons and slider on habpanel don’t work properly, eg if I click it, it will take a noticeable amount of time to change state. Or the button will flicker (turn on, go back to off, then back on) if I leave autoupdate on

I think this illustrates what I’m seeing best. Here’s comparison of log outputs from me changing a thermostat item (modbus register on a plc).

On v1 binding it happens near instantly:

2019-06-20 04:57:45.981 [ome.event.ItemCommandEvent] - Item 'Thermostat' received command 78
2019-06-20 04:57:46.017 [vent.ItemStateChangedEvent] - Thermostat changed from 77 to 78

On v2 it takes much longer, and the item state flips back and forth:

2019-06-20 04:48:48.440 [ome.event.ItemCommandEvent] - Item 'Thermostat' received command 78
2019-06-20 04:48:48.441 [nt.ItemStatePredictedEvent] - Thermostat predicted to become 78
2019-06-20 04:48:48.443 [vent.ItemStateChangedEvent] - Thermostat changed from 77 to 78
2019-06-20 04:48:48.655 [vent.ItemStateChangedEvent] - Thermostat changed from 78 to 77
2019-06-20 04:48:49.079 [vent.ItemStateChangedEvent] - Thermostat changed from 77 to 78

Note that both installs have the same default of autoupdate being on. autoupdate was not disabled in either install. I tried disabling it with the v2 binding - it at least stopped the number flip flopping, however it made the item take a very long time to update - so much so that tapping the button in habpanel feels like it’s broken.

I don’t have much knowledge about the inner workings of either binding, but it seems it could possibly be a change in the way the modbus binding reports item state changes to openhab. I say this because it seems the v2 binding is actually polling my PLC faster than v1. To try and fix this by cutting down on poll time, I even combined ~110 registers needing polled to ~30, so I know the v2 binding is getting the data from my plc faster than before, but the way openhab is updating is several times slower.

short example of my new modbus config:

Bridge modbus:tcp:PLC [ host="", port=502, id=2, connectTimeoutMillis=1000, timeBetweenTransactionsMillis=0, timeBetweenReconnectMillis=0, reconnectAfterMillis=60000 ] {

    Bridge poller slave17 [ start=01, length=1, refresh=100, type="holding" ] {
		Thing data thermostat [ readStart="01", readValueType="int16", writeStart="01", writeValueType="int16", writeType="holding" ]

    Bridge poller slave38 [ start=04, length=1, refresh=100, type="coil" ] {
		Thing data test [ readStart="04", readValueType="bit", writeStart="04", writeValueType="bit", writeType="coil" ]
    Bridge poller slave54 [ start=06, length=1, refresh=100, type="holding" ] {
		Thing data setback_thermostat [ readStart="06", readValueType="int16", writeStart="06", writeValueType="int16", writeType="holding" ]
    Bridge poller slave60 [ start=15, length=4, refresh=100, type="holding" ] {
		Thing data remote_temp_plc [ readStart="15", readValueType="int16", writeStart="15", writeValueType="int16", writeType="holding" ]
		Thing data outdoor_temp_plc [ readStart="16", readValueType="int16", writeStart="16", writeValueType="int16", writeType="holding" ]
		Thing data basement_bedroom_setpoint [ readStart="18", readValueType="int16", writeStart="18", writeValueType="int16", writeType="holding" ]

you’ll note I’ve already cranked the timing down as much as possible. Not sure what else to try. @ssalonen

Now that I think of it, could this be an issue with the way the binding is talking to the autoupdate stuff? from the flip flopping, it seems like autoupdate is instantly (predictively) updating the item sate to the correct value in both v1 and v2 bindings - but in the v2 binding, it changes back to the old value, as if the modbus binding forced an update to the item with the existing value before writing the new value to the plc itself. then the write happens, the plc changes its value, so the modbus binding next poll sets the item to that new value and that is the flip flopping I’m seeing?

I guess it is possible my plc takes long enough to poll that it’s always been this “slow”, but in v1 autoupdate was working properly enough to hide that from me when using the habpanel interface

This is exactly its job.
Why you see odd reversals during a command execution is explained in the Modbus binding docs, and you have worked it out for yourself too.
It’s a consequence of polling data, not of Modbus particularly.
When you get timely poll data, you don’t need/want autoupdate.
Having said that, autupdate has minimal performance impact and ‘unwanted’ is only about nuisance logs etc.

What you’re seeing with it though, highlights that you’ve got a traffic jam with your Modbus transactions.

Okay, so let’s see if we can’t improve your performance.

I note you’ve got pollers set for refresh=100, poll every 100mS. All of them?
That might be optimistic.
The binding maintains a queue for MB transactions; your pollers will add something every 100mS and the binding works through the queue. Sounds like your queue is never emptying, so commands have to wait.

You can see that winding up the poll rate is counter productive - I would be a bit more modest, say 500mS refresh.

You could review individual poll rates - do you really need to read room temperatures more often than five minutes? Obviously for each poller, you’d have to set the rate to the most frequently wanted registers in that block.

Reducing transactions would be good. Maybe your slave doesn’t support this, but many will let you read poll a block of registers that includes undefined addresses. (We’d ignore those at OH end of course)
Example, you have

Bridge poller slave54 [ start=06, length=1, refresh=100, type="holding" ] {
Bridge poller slave60 [ start=15, length=4, refresh=100, type="holding" ] {

which could be combined into one

Bridge poller slave54 [ start=06, length=15, refresh=500, type="holding" ] {

Less transactions! Overhead from fetching more registers is minimal, less transactions is more useful. You keep the same data Things (but will need to alter channel refs in Items) and ignore unwanted registers.

Not specific to Modbus, but again about polling data. Review your persistence strategy. It is all too easy to persist every OH Item and select every update, introducing a big load to your persistence I/O. That’ll give a knock-on effect everywhere.
The v2 modbus binding can generate more Item updates than v1, which will highlight any underlying issues here.

Wait a minute … “more updates”? I promise I’ll come back to that later.

1 Like

Okay, updates.
Again it’s inherent in frequent polling and not particularly Modbus, but the default condition would be updating all your 100 Items every poll. That presents workload for the binding (converting registers to requested states), for openHAB events bus, and as we’ve mentioned perhaps persistence, and logging, making a load on your system filesyste.

v1 MB binding provided a updateunchangeditems parameter, set to false by default. This made the binding only issue updates when an Item state would be changed by freshly polled data. Thus avoiding that extra work.
Note that this acted by default since about version 1.8, you may have been unaware of it.

The v2 binding provides something similar but different. Each data Thing has an updateUnchangedValuesEveryMillis parameter, set to 1000 by default.
Here the binding issues an Item update immediately upon a MB register change; but if the register doesn’t change at a poll, the update to the same value will only take place if it is more than 1000mS since last update.

A typical user might poll once per second, and so with default settings get an Item update every poll. This is different default behaviour to v1 binding. Not a big deal, until you have hundreds of Items…

You can set this parameter to some very large value (days!), and hardly ever get Item updates unless the Modbus register changes. A more typical setting might be for some minutes.

In case you use expire binding to check for failures (by looking for missed updates) note the interaction here, you’d want updateunchangeditems + poll period to be less than the expire timeout.

1 Like

This. I would try this out if it would help out. Perhaps we need to highlight this more clearly in docs…

Maybe, I’m a bit reluctant to present it as a cure-all though. As seen in this thread, there are a bunch of performance related issues/settings associated with fast polling bindings, such as persistence knock-on.

I think I might write up a companion tutorial to “error management” on performance.

1 Like