pragtical / pragtical

The practical and pragmatic code editor.
https://pragtical.dev
MIT License
452 stars 16 forks source link

High input lag #140

Closed AmerM137 closed 3 days ago

AmerM137 commented 3 weeks ago

I've been using Pragtical for a few weeks and I noticed higher than usual input lag compared to other editors. I compared it directly to LiteXL and it looks like there's about a ~2x increase in input lag. I am including data from Sublime & Vscode also for comparison.

stat LiteXL Pragtical Sublime VSCode
mean 11.07 28.22 16.36 16.26
std 3.31 5.35 4.40 4.09

Program used to measure input latency -> https://github.com/pavelfatin/typometer Even though it's a little buggy (sometimes it freezes and stops collecting data), I am confident the measurements translate to user experience. As an example, I felt high input lag when running an IPython REPL inside VSCode's integrated terminal. I measured it with typometer and it turned out that my latency is ~50ms which is not easy to ignore.

@jgmdev I am happy to help with this issue, I just don't know where to start. Let me know what I can do.

Note: the issue has been ongoing for a few versions now. This is not a regression caused by the latest version.

System specs: Windows 11 Pro -- Version 10.0.22631 Build 22631 Pragtical v3.4.2-jit

jgmdev commented 3 weeks ago

If the data is correct then maybe some of the commits here affected the performance https://github.com/pragtical/pragtical/commits/master/data/core/doc/init.lua

I would suspect of the followings:

You could try reverting some of those and seeing how it goes, or some of the others shown on the commit history of data/core/doc/init.lua

Another way of checking what is slowing things down is by using the profiler plugin: https://github.com/pragtical/plugins/tree/master/plugins/profiler

Also, is a good idea to take into account the enabled plugins, for example, have the same plugins on both lite-xl and pragtical just to make sure it isn't a plugin.

quesada commented 1 week ago

FWIW I'm also very interested in having low latency typing. I would try to replicate the measurements with typometer but I don't have any computer not running wayland right now :(

jgmdev commented 1 week ago

So I was doing some testing on my older MacBook Air and noticed the struggle for the machine when typing with lsp and much worse with the scm plugin enabled, so decided to take a crack on the co-routine scheduler (if it can be called that...) and made some adjustments to it as described here #174

@AmerM137 Can you give it a try? You should be able to measure it properly.

You would just need to replace core/init.lua with the linked file.

Still, I need to make the scm plugin behave better because recently noticed that it struggles under windows or low end systems. This update to scm https://github.com/pragtical/scm/pull/7 reduces the amount of updates to certain events which reduces the impact on the responsiveness of the editor.

jgmdev commented 1 week ago

Did some more tweaking... Instead of setting a 50% error margin on the maximum execution time of co-routines, on each run_threads iteration we check how many threads can be run without exceeding the maximum time allowed.

Updated Version: https://github.com/pragtical/pragtical/blob/ef5cb0455814a0b03bca9cb5a26f9ecbd451e1bc/data/core/init.lua

AmerM137 commented 1 week ago

Exciting stuff. I'll give it a shot and update my numbers very soon!

jgmdev commented 6 days ago

Made some more changes:

Use the avg. runtime of co-routines to yield

We now keep track of every 1 second cycle in order to see how much time is left for executing co-routine tasks, by using the average execution time of co-routines to decide if we should execute it or skip it until next 1 second cycle.

Also these changes introduce core.fps which has the maximum frames per second that are actually possible to render, which can be used to accommodate to frame drops when performing some animations, scrolling, etc...

Looking forward for your results!

jgmdev commented 5 days ago

More stuff to improve overall editor responsiveness in scenarios where files with huge long lines are opened like compressed css or js files:

jgmdev commented 5 days ago

Some videos showing a small test using this file https://github.com/digidoor/SICP/blob/master/theme.css. Without additional plugins it shows input lag on lite-xl and scrolling, meanwhile on Pragtical scrolling is smoother and input is faster. With additional plugins Lite XL interface doesn't even responds while on Pragtical you can still edit the file.

Test

Vanilla Lite XL (master branch)

https://github.com/user-attachments/assets/b0b64d1f-2603-400c-b63b-0a121bce767d

Vanilla Pragtical (co-routine improvements)

https://github.com/user-attachments/assets/4d07a2d1-54ea-4f89-bf27-b91c1827dc81

Lite XL with Plugins (drawwhitespace, colorpreview, rainbowparens, minimap, indentguide, lsp)

Becomes unresponsive

Pragtical with Plugins (drawwhitespace, colorpreview, rainbowparens, minimap, indentguide, lsp and more)

https://github.com/user-attachments/assets/381d1a01-4f5d-427f-adff-a8a37fe46dea

AmerM137 commented 4 days ago

New results tested at different fps. There is a clear improvement in input latency only when increasing fps. At 60 fps, It's only a marginal improvement vs other editors.

Built from PR #174 on windows with meson. Transitions off.

stat 60fps 90fps 120fps 144fps
mean 24.24 21.67 18.71 19.00
std 5.72 4.51 3.02 2.62
jgmdev commented 4 days ago

Thanks @AmerM137 for your test results, I think I finally got it with latest changes:

Main loop: burst events procecssing for 3s - When receiving events we reduce the wait time to match the rendering speed for the events that follow in order to process them earlier and reduce the input lag.

Input latency should be lower than lite-xl now:

Reduced Input Lag Test

https://github.com/user-attachments/assets/f57cf694-fa44-4bce-b693-8ca4a4b2a8fe

Testing Patch Against Latest PR Changes

diff --git a/data/core/init.lua b/data/core/init.lua
index 4bd8339c..ed2da295 100644
--- a/data/core/init.lua
+++ b/data/core/init.lua
@@ -1346,11 +1346,14 @@ local cycle_end_time = 0
 ---@type number
 local main_loop_time = 0

+local event_start_time = nil
 function core.step()
   -- handle events
   local did_keymap = false

+  local is_textinput = false
   for type, a,b,c,d in system.poll_event do
+    is_textinput = type == "textinput"
     if type == "textinput" and did_keymap then
       did_keymap = false
     elseif type == "mousemoved" then
@@ -1405,6 +1408,10 @@ function core.step()
   core.root_view:draw()
   renderer.end_frame()

+  if is_textinput then
+    print((system.get_time() - event_start_time) * 1000, "ms")
+  end
+
   rendering_speed = math.max(0.001, system.get_time() - start_time)

   if rendering_speed * config.fps < 1 then
@@ -1583,6 +1590,7 @@ function core.run()
       end
     else
       -- run all threads, listen events and perform drawing as needed
+      event_start_time = system.get_time()
       local did_redraw = false
       if not next_step or system.get_time() >= next_step then
         did_redraw = core.step()
jgmdev commented 4 days ago

Ok, so did my own benchmarks using TypoMeter and here are the results of that application:

typometer-results

With the input generated by TypoMeter and the testing patch posted on previous comment applied to both Pragtical and Lite XL, here are the results taken directly from the applications themself, measuring the time since registering the input event until the character is rendered on the interface:

Editor  Min Max Average
Pragtical 1.9058650000261 2.8339249997771 2.19647337500755
Lite XL 3.4161069997936 52.384641000117 36.695156788055

It seems that TypoMeter has issues measuring fast responses and system hiccups can cause the application to report incorrect values resulting on inconsistent results.

I think we should be good to merge. Going to test a bit more while doing some work with the editor.

AmerM137 commented 3 days ago

Sounds good! I agree that typometer can be very finnicky. It would be great to have our own profiling tool in the editor. I used your patch and here are my numbers. It's looking really good!

@jgmdev it would be great if we make it easy to run these kinds of tests from within Pragtical. Can the input latency profiler become a simple plugin maybe?

image
jgmdev commented 3 days ago

@jgmdev it would be great if we make it easy to run these kinds of tests from within Pragtical. Can the input latency profiler become a simple plugin maybe?

Stitched something together just now and pushed it to plugins repo: https://github.com/pragtical/plugins/blob/master/plugins/input_latency.lua