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

Maximum speed configuration? #110

Open
JakubFojtik opened this issue Mar 7, 2020 · 7 comments
Open

Maximum speed configuration? #110

JakubFojtik opened this issue Mar 7, 2020 · 7 comments

Comments

@JakubFojtik
Copy link

JakubFojtik commented Mar 7, 2020

What arguments would cause the maximum execution speed of the setvcp command run one after another?

I am using --noverify --sleep-multiplier 0.1, but the command sometimes needs retrying due to the low multiplier.

Are there other ways to increase speed, like opening a "socket" and reusing it?

I wanted to match the speed of the proprietary I-Menu for AOC monitors, where one can change brightness via a slider real-time. Is that posible with ddcutil's I2C, or are they using their own proprietary protocols?

@rockowitz
Copy link
Owner

rockowitz commented Mar 7, 2020 via email

@ashutoshgngwr
Copy link

ashutoshgngwr commented Sep 19, 2023

AFAIK, MonitorControl also uses the DDC protocol to do this in real-time on MacOS. Its brightness sliders are smooth. Perhaps it might help.

@Cimbali
Copy link

Cimbali commented Oct 9, 2023

I’ve had similar smooth experience on Windows, with Twinkle Tray which seems to use node-ddcci as a library to call low level windows API functions such as SetVCPFeature.

Note that I’m sure a 100ms delay is barely noticeable in a slider unless you’re looking for it. But currently with ddcutil 2.0 I see things like:

> time ddcutil -b 1 setvcp 10 100

real    0m3.007s
user    0m0.010s
sys     0m0.067s

So 10ms of user time, 67ms of kernel time, but 3 full seconds of wall clock time -- specifying the bus directly. Not on all monitors thankfully, but even on a faster one there’s at least a lot of variability:

> time ddcutil -b 10 setvcp 10 100

real    0m0.547s
user    0m0.006s
sys     0m0.013s
> time ddcutil -b 10 setvcp 10 100

real    0m0.401s
user    0m0.012s
sys     0m0.006s
> time ddcutil -b 10 setvcp 10 100

real    0m0.167s
user    0m0.008s
sys     0m0.009s

The only other linux implementation I found is based on i2c-tools, e.g. python-ddci. That seems to be more error-prone as on the bus that performs slower with ddcutil the ddcli command returns without actually modifying the brightness 3 out of 4 times. (ddcutil also fails but much less frequently with “VCP (aka MCCS) version for display is undetected or less than 2.0. Interpretation may not be accurate. Verification failed for feature 10“). Besides it being less reliable, it is blazingly fast:

> time ./ddccli.py -b 1 --brightness 10

real    0m0.028s
user    0m0.019s
sys     0m0.009s

> time ./ddccli.py -b 1 --brightness 100

real    0m0.030s
user    0m0.017s
sys     0m0.013s

> time ./ddccli.py -b 10 --brightness 10

real    0m0.031s
user    0m0.021s
sys     0m0.006s

> time ./ddccli.py -b 10 --brightness 100

real    0m0.038s
user    0m0.027s
sys     0m0.007s

So it’s likely the python-ddci/i2c-tools is skipping a lot of possibly mandatory things, but maybe there could be some inspiration taken from there to make things faster?

@rockowitz
Copy link
Owner

rockowitz commented Oct 10, 2023

@Cimbali Is this performance problem new with release 2.0? If so, it might be related to the newly introduced dynamic sleep algorithm, and that needs to be diagnosed.

Before doing anything else, make a copy of $HOME/.cache/ddcutil/dsa so that your accumulated data is not affected by subsequent tests. Next please run sudo ddcutil interrogate and save the output. The output is voluminous, but it avoids a back and forth over lots of little questions. Submit both files as attachments of some sort.

Options --stats and --vstats provide lots of detail about where ddcutil is spending its time and how many I2C retries are required. The latter breaks down the stats by monitor. (If the issue is in the new dynamic sleep algorithm, option --istats dumps internal information as well.)

My guess is that the DDC implementation for the display on bus 1 is marginal, and that the stats will show lots of retries. Assuming the runs on bus 10 are sequential, the decreasing elapsed time would reflect the tuning as dynamic sleep reduces the sleep multiplier.

Try running with option --disable-dynamic-sleep and use option --sleep-multiplier to explicitly set the multiplier factor to be used. Can you find a sleep multiplier value that improves performance? If so, there may be a problem with the dynamic sleep algorithm.

Yes, ddcutil does a lot of checking that python -ddci does not, so it probably works more reliably with your marginal monitor, at the expense of performance. In particular, setvcp automatically performs a getvcp operation to verify that the monitor's value has changed. python-ddcci does not appear to perform that check. Running ddcutil with option --noverify would make its performance more comparable to python-ddcci.

i2c-tools is basically a thin application over driver i2c-dev. ddcutil makes essentially the same system calls to i2c-dev as does i2c-tools.

Regarding Windows, the API functions such as SetVCPFeature are at a much higher level than the I2C interface provided by i2c-dev. If ddcutil were ported to Windows the lowest layers of ddcutil would simply be stripped out. Plus, the Windows video drivers simply have better I2C support. I'm not surprised that DDC performance is better on Windows.

@Cimbali
Copy link

Cimbali commented Oct 16, 2023

It’s not new with 2.0, it was already there before -- I was just hoping 2.0 would fix it.

I have an applet to control monitor brightness and was hoping to use DDC rather than xrandr --brightness. In that use case (by scrolling or with a slider), a very large response time is not ideal (3s is not usable, but I’m sure some people could tolerate up to 0.5s).

I understand your new sleep algorithm is dynamically reducing or increasing the sleep multiplier based on previous calls. Is there a way to profile that value? Say on detecting a new screen is connected, run a dozen dummy commands (or brightness -1% / +1%), or until the value has converged?

@rockowitz
Copy link
Owner

I agree that 3.0s execution time for individual ddcutil calls makes it unusable for a scrollbar in an app. The real solution is to use the shared library which performs initialization once, but I appreciate that until libddcutil has a python interface that is impractical for most developers. You might want to take a look at how vdu_controls gets around this problem.

Tuning the dynamic sleep-multiplier requires a large number of calls. Doing this automatically when a new monitor is detected would make the initial ddcutil call so slow that it would be perceived as failing. However, your app could have an option to perform a long running profile operation by making a large number of getvcp calls (and hiding the output) on user request.

@rockowitz
Copy link
Owner

@Cimbali, I have added an experimental option to branch 2.0.2-dev, -skip-ddc-checks. It is valid only if the display is selected by its bus number (option --bus) and only for commands getvcp and setvcp. Because it is experimental, it is listed only by option --hh, not --help.

If specified, ddcutil initialization does not check if DDC communication is working, and does not check that the monitor reports unsupported features as per the DDC/CI spec, For any "reasonable" monitor, these checks should never fail. The downside is that either of these things is not true, it's unclear how the getvcp or setvcp command will fail.

Also, to make the slider more responsive and if you have not already done so, consider using option --noverify on the setvcp calls, and only call getvcp once after the slider operation is complete to get the final value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants