Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(inputs.modbus): Optimize requests #11273

Merged
merged 6 commits into from
Nov 14, 2022
Merged

Conversation

srebhan
Copy link
Contributor

@srebhan srebhan commented Jun 8, 2022

resolves #12222

This PR adds a optimization parameter that allows for optimizing requests sent to the device. Currently there are four modes,

  • none doing nothing besides confirming to the max request size and ignoring empty requests
  • shrink removing leading and trailing fields that are omitted
  • rearrange moving the request boundaries in order to reduce the total request size further while keeping the number of requests
  • aggressive automatically fill gaps in requests in order to reduce their number

to try to reduce the number of requests sent to the device while covering all fields.

@telegraf-tiger telegraf-tiger bot added the feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin label Jun 8, 2022
@TimurDela
Copy link
Contributor

TimurDela commented Jun 18, 2022

Dear @srebhan ,
I am sorry it took me so long to answer you on this.
Nice work with the aggressive optimisation that allows reducing the number of requests even further.
Please note that there must be some bug in the rearrange method that in some cases ends up in an infinite loop. Try running your unit test TestRequestOptimizationShrink by setting optimize to rearrange instead of shrink, go will panic.

However, I have been doing some reading concerning modbus and it looks like minimising the number of requests is not always the optimal solution. Each request comes with a cost but each field as well, this means that sometimes it can be better to split a large request into two if this means not touching many addresses we are not interested in. See this publication.

How much time it takes for each extra request and each extra field depends on the hardware and the network so there is no generic answer to what is optimal. One needs to try, measure, try, measure.

One approach that I found online is the following: set a limit on the number of "omitted" fields you are willing to accommodate in order to reduce the number of requests and optimise accordingly.

I have pushed on #11106 a possible implementation of this. Instead of choosing an optimisation mode, the user would set the value of max_extra_register between 0 (as many requests as non-consecutive fields) and 125 (as few requests as possible, whatever their size). As you can see, this requires minor changes to the actual code (only a few lines).
I have added your "aggressive" unit test and it passes but with two different values of the max_extra_register parameter.
This means no risk of infinite loops and a much faster startup (the aggressive optimisation takes a few seconds to make the list of requests).

The problem I see, however, is that I do not see how the user would choose the value of max_extra_register that optimises their hardware plus network setup.
If one runs time telegraf --test, over a single interaction, the duration tends to fluctuate a bit and it is hard to see if it got better or worse. Is there a way to do telegraf --test 10 to test the input 10 times in a row?

@srebhan
Copy link
Contributor Author

srebhan commented Jun 22, 2022

@TimurDela thanks for taking the time to test this!

Regarding the panic and the infinite loop:
You cannot set rearrange in TestRequestOptimizationShrink as it will take forever (thus the panic probably) as the worst-case scenario is to hard for the current implementation. This is because we brute-force recursively optimize between group borders which scales with O(N!) where N is the number of groups. Therefore I added the big-fat warning in the readme...
We probably can do better, but I didn't have time to look more deeply...

Regarding the tradeoff between requests vs. number of registers... Currently, rearrange minimizes the number of registers without changing the number of requests by moving the request borders around! For aggressive I do agree with your observation to add a optimization_max_fill parameter. Feel free to implement it on the basis of this PR as I intentionally implemented the underlying things in a way that people can add more strategies later.

@srebhan srebhan force-pushed the modbus branch 2 times, most recently from dc6b1d1 to 43e5f00 Compare July 7, 2022 13:36
@TimurDela
Copy link
Contributor

TimurDela commented Sep 7, 2022

Hello @srebhan,
sorry it took me so long but with holidays and then other tasks to work on, I only found the time to work on this now.
The code is ready for your review but I do not have the rights to push to your repo srebhan/telegraf:modbus. Can you please explain to me how I add code to this pull-request?

I have tried to rebase my branch on master, merge your changes and then add mine but the first step has closed the pull request #11106 and my subsequent push have not reopened it, even though it says
No new commits influxdata: modbus_request_grouping_#11105 was force-pushed and no longer has any new commits. Pushing new commits will allow the pull request to be re-opened.

Do you have the possibility to re-open PR #11106 ?

As you can see, on my fork, I have both your changes and mine: fork

@TimurDela
Copy link
Contributor

Hello @srebhan,
sorry to insist. Is there any way to reopen PR #11106 or should I start a new one?

@MyaLongmire
Copy link
Contributor

MyaLongmire commented Sep 13, 2022

@TimurDela I have reopened your pr :)

@TimurDela
Copy link
Contributor

Thank you @MyaLongmire but it looks like I have lost the possibility to modify the PR. It is now a draft but I cannot change its status to open nor ask for reviews. Is there something you can do in the settings of the PR?

@powersj
Copy link
Contributor

powersj commented Sep 21, 2022

@srebhan - If I followed the comments correctly, we are favoring #11106 over this PR?

@powersj powersj added the waiting for response waiting for response from contributor label Sep 21, 2022
@srebhan
Copy link
Contributor Author

srebhan commented Sep 27, 2022

@powersj and @TimurDela if you both agree I would like to first merge this PR and then add #11106 which extends this code in a nice way. This way, #11106 becomes smaller and can serve as an example of what needs to be done to add more optimization schemes...
What do you think?

@telegraf-tiger telegraf-tiger bot removed the waiting for response waiting for response from contributor label Sep 27, 2022
@srebhan srebhan requested a review from powersj November 14, 2022 15:55
@srebhan srebhan added area/modbus plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins labels Nov 14, 2022
@srebhan srebhan changed the title feat: Modbus request optimization feat(inputs.modbus): Optimize requests Nov 14, 2022
@telegraf-tiger
Copy link
Contributor

Copy link
Contributor

@powersj powersj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @srebhan!

@powersj powersj added the ready for final review This pull request has been reviewed and/or tested by multiple users and is ready for a final review. label Nov 14, 2022
@srebhan srebhan merged commit 2ade360 into influxdata:master Nov 14, 2022
@srebhan srebhan deleted the modbus branch November 14, 2022 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/modbus feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins ready for final review This pull request has been reviewed and/or tested by multiple users and is ready for a final review.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

inputs.modbus: Read register span in one go and drop unused fields
4 participants