-
-
Notifications
You must be signed in to change notification settings - Fork 185
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
Lag when holding cursor movement in input window #1246
Comments
Right, happens to me too. Don't know yet why. @pasis do you see why this happens? |
I can reproduce the issue too with release 0.7.1. It is very noticeable when the keyboard repeat speed is high like 60Hz, such as with
|
Hi, sorry for the long delay. This problem only is quite noticeable in a machine that I only use a few days a year. It seems to be caused by the
This is the backtrace of that select:
To test my hypothesis I set the timeout of the select to 1 ms, using:
After that, it runs nicely when I keep the arrow pressed. However I believe interrupting the main event thread with select to check the network for new events is a bad design for performance. I think it can be avoided by using another thread or a poll-based approach. I'll try to take a look and find a proper fix, hopefully soon :) |
Hi, again I think I would like to expand a bit my answer. There are a two problems I discovered while trying to find why pressing the arrows takes too long (or pasting a lot of text) and also why this issue is not immediately obvious to debug. In order to find what is happening I first used In my experiments I pressed one arrow key (I believe which doesn't matter, as long as you cause any input) while the profanity process is being recorded by perf (the arrow keys amplify by 3x any slowdown, as one keypress sends 3 bytes). I kept the arrow key pressed during about 5 seconds. It is very important that you are connected to a xmpp server that doesn't cause a lot of traffic, otherwise you may not be able to reproduce it. Here is what you get with
High CPU when disconnectedIn this machine I have configured the keyboard to emit events at 83 Hz when I keep the arrow pressed, so it will input three bytes (one arrow key emits three bytes) every ~12 ms. However, you can see that when it is disconnected, it is taking almost half the CPU time (43%) to cope with the input rate. This means that updating the screen after an input byte takes about 2 ms of CPU time (in average), which is a lot. Notice that the only thing that it should be happening is that it should receive one key press, and update the cursor position. If you take a look with
This information shows that profanity is using quite a lot of CPU to update the screen with pnoutrefresh(), but it is still capable of digesting the keypresses at 83 Hz (otherwise the CPU would be 100%). It should not be noticeable when typing, but it may introduce quite a large delay when pasting a large input. This could be easily avoided by only updating the screen if the last refresh happened more than say 1/60 s ago. This problem is not noticeable in general and I believe is not what @320x200 was experimenting. The other problem happens only when profanity is connected to a server. Very slow when connected but low CPU usageWhen you connect profanity to a xmpp server, the slowdown is very noticeable. In order to se what is going on, I used the newer You can see that most of the time is spent sleeping (gray color), and only works on regular intervals (the blue thin lines). Every blue line is one key being processed. The problem with I believe the issue #225 is also the select problem, otherwise you would see 100% CPU usage:
You can only reach to that point with profanity disconnected (no select) after pasting about 10^6 bytes:
So I think the only problem noticeable now is the 10 ms select timeout. This problem can be solved by modifying the libstrophe library to implement a polling mechanism (like the one provided by the GMainLoop, as you suggested) and then adding it to profanity too. Using a polling event loop is the easiest implementation, as you won't need to bother with thread safety (only one thread will call your library). Additionally, you get for free priority scheduling, so you can assign more priority to the user key events, and always process first the keyboard events. I believe such a change doesn't require a lot of work, as we only need to replace the two select() with the event loop mechanism. Additionally, libstrophe also uses the glib, so the event loop support is already there. I think I will first try to modify libstrophe and profanity to be used with GMainLoop and see how that goes. Notice that this will only fix one of the problems, the high usage of CPU should be fixed later. |
Thanks a lot for this detailed report!
It doesn't :-)
Looking forward to it! :-) |
Hi,
Ups, sorry I mixed things up when reading the source of libstrophe and loudmouth, the XMPP library of mcabber (which it does). Then it would be nice if I can avoid adding a new dependency :)
I've come up with what it lloks like a plan which I can test in small increments.
Then, as soon as new activity is detected in the libstrophe fds, we call a modified version of I believe this would solve both problems, but let's see :-) |
I got the two first points working, but adding polling support in libstrophe may be a bit tricky, as they also have timeouts in their own main loop. Adding a callback for each connection is not really needed as profanity handles all xmpp connections (only two, connect and register aparently) so we already have a pointer to each xmpp_conn and we can get the socket. Furthermore, the tls connections are currently using the same socket in conn->sock, so activity in the socket given by the polling mechanism would work fine. I did a dirty workaround where I extracted the socket from the offset of the xmpp_conn opaque typedef and I was able to build a gsource so that the GMainLoop can detect when incoming activity is detected in the main connection. With this hack, I can determine when I can safely call the The problem is that I also need to progress in queued data which needs to be sent and also handle the timeouts. I could call a stripped down version of xmpp_run_once which doesn't perform the select(), only sending data and the timeouts and call that from time to time. While the incoming data would be processed by a callback called from the GMainLoop. However, that would waste CPU and I believe it can be avoided by determining when is actually required to call the progress function. We can add a idle function in the main loop which is activated only when the user has caused some xmpp data to be queued. Also, we can handle the timers by first asking libstrophe for the time of the first timer and then adding a timeout callback in our main loop which in turn updates the timeout for the next call. I believe this design would be the most efficient. From libstrophe I would need a way to retrieve the |
You could create a (draft) pull request for this already. Easier for people to check what's worked on then :) |
Expected Behavior
After holding a cursor movement key (like left or right arrow keys) there should not be any delay after releasing the key.
Current Behavior
After holding a cursor movement key, the key action (cursor movement) keeps on a repeating for a duration proportional to the time the key was held, as if profanity is not able to keep up with key input speed and an event queue is building up, which may explain why once released, the action keeps on repeating.
Steps to Reproduce
Write a long text in the input window. Go back and forth with the arrow keys (holding the keys), notice the lag/delay.
Context
I noticed that while wanting to go back towards the beginning of a long sentence to edit it and while releasing the arrow key to go back, the cursor kept moving for some time.
Environment
profanity -v
FreeBSD 12.1-STABLE r354337 GENERIC amd64
2.56.3_6,1
The text was updated successfully, but these errors were encountered: