jquast / blessed

Blessed is an easy, practical library for making python terminal apps

Home Page:http://pypi.python.org/pypi/blessed

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

kbhit busy waits on windows

Numerlor opened this issue · comments

The current win_terminal implementation of kbhit busy waits for mscvcrt.kbhit to return true and eats up all of the cpu cycles given to it. A short (optional?) sleep at the end of the loop should solve this issue without influencing the behaviour much - only potentially delaying the first kbhit's dispatch by a small amount of time

while True:
if msvcrt.kbhit():
return True
if timeout is not None and end < time.time():
break
return False

While I generally agree adding a 1 - 10 milliseconds would reduce the CPU load and likely go unnoticed by the user, the issue is with time granularity on Windows which isn't very granular by default on Windows and can have unexpected consequences for not only the current process, but, for Windows versions prior to 10 2014, other processes.

While I generally agree adding a 1 - 10 milliseconds would reduce the CPU load and likely go unnoticed by the user, the issue is with time granularity on Windows which isn't very granular by default on Windows and can have unexpected consequences for not only the current process, but, for Windows versions prior to 10 2014, other processes.

For my use the default resolution seemed to be enough to not be noticeable (with a 0.01sec sleep which takes ~15.7 ms on my system), although I'm not very familiar with terminal input handling and how it could affect other situations.

If the delay could be an issue, I think that at least adding it and making it optional and documenting that will be worth it as I'd assume most users don't expect a simple input request to eat up a core.

I think an optional value passed as an argument to kbhit() would be reasonable, but it would have to be applied in blessed.terminal.Terminal and blessed.win_terminal.Terminal. It would also need to be an argument to inkey() and passed down.

@jquast should weigh in, but you're welcome to submit a pull request.

I think an optional value passed as an argument to kbhit() would be reasonable, but it would have to be applied in blessed.terminal.Terminal and blessed.win_terminal.Terminal. It would also need to be an argument to inkey() and passed down.

@​jquast should weigh in, but you're welcome to submit a pull request.

Sounds good, just got a couple of things I want to be sure of:
With blessed.terminal.Terminal, would the arg just be ignored? I'm not familiar with how the system works there but it doesn't look like the current approach eats up the CPU like the loop on win.
Also, should the parameter default to be disabled, to maintain the behaviour from the previous version, or ste to something like 0.01 I used above to prevent issues for unaware users?

I really wouldn't mind a sleep 0.01 call in win_terminal.py, with a docstring to say, "On windows platforms not using WSL, there may be an additional delay of up to 20ms for keyboard input" and a brief comment and link this issue for the reason of the sleep.

If somebody would really want to remove the ~20ms delay at expense of CPU, they can derive & override the method with the sleep call removed.

I recently purchased a Windows 10 Machine w/latest-gen desktop CPU for C# stuff, though I don't know what exactly is at fault, all input fields have awful latency -- I can type full words, sometimes multiple words, into basic Windows UI elements before they begin to display. I can't hardly believe it! I guess it's because it has a mechanical disk, windows Defender real-time protection that won't stay disabled, or the plethora of Spectre mitigations, but the input latency is higher than any computer and operating system I have ever used in history.

So, I don't think 10ms will make a difference!

I had started to write the same thing until I was pulled away to cut up a branch that fell in the neighbor's yard. time.sleep(0.01) will likely go unnoticed. This should default to 15.6ms (Windows default time granularity), and, if someone increased the time granularity, it would be 10ms. Both seem reasonable for detecting key presses. Sorry I steered you down the wrong path before.