victronenergy / venus

Victron Energy Unix/Linux OS
https://github.com/victronenergy/venus/wiki
545 stars 70 forks source link

D-Bus ItemsChanged: reduce CPU load caused by D-Bus traffic #789

Open mpvader opened 3 years ago

mpvader commented 3 years ago

Reducing D-Bus traffic - increasing scalability

For example a solar charger, sends multiple PropertiesChanged signals every second, one for each D-Bus path. Also cgwacs and dbus-fronius do: 9 signals per second per PV inverter. And for reference, on a CCGX, the max signals per second is approx 30.

The idea is to send only one every (for example) second, from root, with a Dict with all paths that have an updated value.

The plan:

  1. [x] 1. Proof of concept and prepare the used Python, C as well as Cpp libs for both receiving and sending dict-updates. Mostly done, except for transmitting from Cpp-based services.
  2. [x] 2. Update all consumers
  3. [x] 3. Update the heavy users: vedirect-interface, vecan-dbus, dbus_fronius and cgwacs - and maybe mk2-dbus if not too difficult?
  4. [x] 4. (ibu) Report again on the difference in CPU load; and discuss its consequences:
  5. [ ] 5. Update the rest of the services, will probably happen only some day
  6. [ ] 6. Once most are over, we might want to move the rest over as well, including localsettings, so we stick to one method, one implementation. To be discussed/decided then.

Services that consume (and thus need updating first)

Consumers that are not immediately required:

Producers of highest prio:

Producers that can be done some day:

Python:

C:

Cpp:

Notes per language:

Python:

In the majority of cases all that is required is updating velib_python after merging dict_updates. In some cases, a project might need a small change, ie. using the with statement notation, to send updates in a batch.

mpvader commented 3 years ago

vedirect-interface branch is here: https://github.com/victronenergy/vedirect_interface/commits/thiemo/WIP_dict_updates

velib branches are here: https://github.com/victronenergy/velib/tree/thiemo/WIP_Item_Dict_Leafs https://github.com/victronenergy/velib/tree/thiemo/WIP_Item_Dict_Producer (added)

velib_python is here: https://github.com/victronenergy/velib_python/tree/dict_updates

izak commented 3 years ago

Some results from testing.

Test environment

  1. Venus 2.65 base system
  2. vedirect-interface replaced with a binary that sends dict updates on root
  3. systemcalc and vrmlogger patched to use velib_python that understands dict updates
  4. gui recompiled with new velib so it understands dict updates
  5. Rest of the system left as is (should have minimal effect on CPU usage).

This was tested vs an unmodified setup.

First test: Test effect on CPU use on a working system

System has:

  1. CCGX
  2. 2 x VE.Direct solar chargers
  3. 1 x Multiplus
  4. 1 x BMV 700
  5. System was set up to feed solar power into the grid, so that there would be constant power changes to communicate.

Unoptimised system

CPU use:

CPU idle: +-30%

Optimised system

CPU use:

CPU idle: +-40% (handsome improvement)

Second test: DBus throughput on a heavily loaded system

System has:

  1. CCGX
  2. 2 x VE.Direct solar chargers
  3. 1 x Multiplus
  4. 1 x BMV 700
  5. System was set up to feed solar power into the grid, so that there would be constant power changes to communicate.
  6. An additional 5 simulated solar chargers that change voltage/power/current values once a second.
  7. dbus-statistics look specifically at PropertiesChanged signals and ignores SetValue/GetValue calls.
  8. Statistics were assessed using wireshark and dbus-monitor's --pcap option.

Unoptimised system

Optimised system

Very heavily loaded optimised system

Another two simulated solarchargers were added, for a total of 7 simulated and 2 real solarchargers (plus a BMV).

Conclusion

Other observations

izak commented 2 years ago

@mpvader I remember now what's holding back improvements on the QT projects.

There is a velib branch (thiemo/WIP_Item_Dict_Leafs) that implements the sending of multiple values in a single message, but only for C projects (this was used for vedirect-interface when doing this evaluation). A C++ implementation is needed.

That same branch has code for receiving multiple values in a single message. This does have a C++ version and was used during testing in the GUI.

velib_python has a dict_updates branch that is fully up to date (python3 ready). It implements a context manager that can be used with a with statement, and it sends everything that happens inside that block together in one message.

What is needed is a C++ implementation that allows grouping and sending multiple values in one PropertiesChanged message.