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

[BUG] text selection very slow with large output #877

Closed
markus-wa opened this issue Nov 17, 2021 · 15 comments
Closed

[BUG] text selection very slow with large output #877

markus-wa opened this issue Nov 17, 2021 · 15 comments

Comments

@markus-wa
Copy link

In Case of Graphical or Performance Issues

Please attach the files that were created in /tmp/zellij-1000/zellij-log/ to the extent you are comfortable with.

zellij-debug.tar.gz

Basic information

zellij --version: 20.1
tput lines: 51
tput cols: 104
uname -av or ver(Windows):

Linux mark-ThinkPad-X1-Extreme-2nd 5.11.0-40-generic #44~20.04.2-Ubuntu SMP Tue Oct 26 18:07:44 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

List of programs you interact with as, PROGRAM --version:
happens in both alacritty and gnome-terminal - neither of them has this issue when not using zellij
alacritty --version: alacritty 0.9.0
gnome-terminal --version: # GNOME Terminal 3.36.2 using VTE 0.60.3 +BIDI +GNUTLS +ICU +SYSTEMD

Further information

$ zellij
$ while :; do; tr -dc A-Za-z0-9 </dev/urandom | head -c 200 ; echo ''; done
wait a while
CTRL+C

select some text - it will be very slow

another quicker way to repro is usually just a simple rg a as it's not as slow as generating random data - but that would have included sensitive stuff in the debug log

$ zellij
$ rg a
CTRL+C

select some text - it will be very slow

it gets really bad at around 50k lines

@imsnif
Copy link
Member

imsnif commented Nov 17, 2021

Thank you!! I have been trying to reproduce this one for a short while. @tlinford - any ideas?

@markus-wa
Copy link
Author

no problem 😄

some more notes:

  • it affects all panes
  • exiting the pane with tons of output solves the issue for other panes 🙂 (but I would expect zellij to handle these volumes without a slowdown, as alacritty and gnome-terminal on their own can handle it fine)

@imsnif
Copy link
Member

imsnif commented Nov 17, 2021

exiting the pane with tons of output solves the issue for other panes slightly_smiling_face (but I would expect zellij to handle these volumes without a slowdown, as alacritty and gnome-terminal on their own can handle it fine)

Yes, for sure! this is likely a small issue somewhere in us looking through the wrong stuff (just a guess, will need to debug this).

@tlinford
Copy link
Contributor

@imsnif I'm thinking it may not be directly related to mouse mode, running rg a shows the same problem also with mouse mode off.
Seems like at a certain point the scrollback stops being capped at 10000 lines for some reason, and after that scrolling is really slow.

@imsnif
Copy link
Member

imsnif commented Nov 17, 2021

I know of this issue with line wrapping. A line with 5 wraps is counted as one line for the scrollback purposes... do you think it's related? Can this be reproduced while filling the scroll buffer with lines no longer than the pane width?

@tlinford
Copy link
Contributor

Looks related indeed, with no line wraps:

for i in range(10000):
  print("hello")

everything smooth.
When lines start wrapping:

for i in range(10000):
  print("hello"*50)

slowdown starts to appear, pretty bad with mouse, not very noticeable with scroll mode.
With:

for i in range(10000):
  print("hello"*1000)

everything becomes sluggish.

@markus-wa
Copy link
Author

markus-wa commented Nov 17, 2021

I don't think wrapping is the (only) issue.

10000 lines of while :; do; tr -dc A-Za-z0-9 </dev/urandom | head -c 200 ; echo ''; done also reproduce the issue (my terminal is over 200 cols wide)

I think it's just the amount of text.

maybe try the same hello test but just keep it slightly short of wrapping

@markus-wa
Copy link
Author

PS: while my machine is reasonably beefy, it's just a laptop - so maybe on a sufficiently strong PC the issue only starts being noticeable after wrapping as it will be a lot more text - but for me it reproduces before wrapping.

@tlinford
Copy link
Contributor

no you are right - it seems the wider the line, the slower it gets, thanks for the insight.

@tlinford
Copy link
Contributor

i think i've found what's happening:
in grid, scrollback_position_and_length, is iterating over all rows, and over each character in every row to calculate the width.
So the more rows in the scrollback buffer, and the wider each row, the slower everything gets.
At the same time while dragging with mouse, we are requesting a ton of rerenders, and they just seem to pile up :)

Did a quick test with some log::infos thrown in to measure how long things are taking (in microseconds):

INFO   |zellij_server::panes::ter| 2021-11-17 14:23:35.618 [screen    ] [zellij-server/src/panes/terminal_pane.rs:248]: finished rendering chunk in: 145
INFO   |zellij_server::panes::ter| 2021-11-17 14:23:35.641 [screen    ] [zellij-server/src/panes/terminal_pane.rs:256]: time to calc scrollback: 23112
INFO   |zellij_server::panes::ter| 2021-11-17 14:23:35.641 [screen    ] [zellij-server/src/panes/terminal_pane.rs:275]: render: 23414

@imsnif
Copy link
Member

imsnif commented Nov 17, 2021

Ahh, nice one! This is done purely for the UI - if you comment out the contents of this function and just return (0, 0) does it fix this?

@tlinford
Copy link
Contributor

yep!

@imsnif
Copy link
Member

imsnif commented Nov 17, 2021

Good find!! Can you think of a way to either cache these numbers or reduce the complexity (or both)?

@tlinford
Copy link
Contributor

well, first thing that comes to mind is to store the width on the row, and update it when it gets mutated.

@imsnif
Copy link
Member

imsnif commented Nov 17, 2021

IMO this path might have some friction in it as it might harm the performance of eg. throwing large amounts of data into the scroll buffer.

I'd try to maybe cache the result of this whole function on TerminalPane somehow and invalidate the cache every time we scroll or move a line from the viewport to lines_above. See if that makes a big enough difference?

@tlinford - if you have the time and feel like taking this up, that'll be cool. If not I'll try to get to it in the next few days.

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

3 participants