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

Termion backend is slow #142

Open
gyscos opened this issue Jun 13, 2017 · 14 comments
Open

Termion backend is slow #142

gyscos opened this issue Jun 13, 2017 · 14 comments

Comments

@gyscos
Copy link
Owner

gyscos commented Jun 13, 2017

When running the lorem example with the termion backend in debug mode, a serious flickering can be observed. Running in release mode seems to solve this. Running in debug mode with the ncurses backend is also fine.
It may be caused by a slow backend. All the calls to print! have to lock individually the standard output.

Note: to be clear, this issue is about the wrapper code in the cursive repository, not about termion itself.

@lilianmoraru
Copy link

lilianmoraru commented Aug 15, 2017

@gyscos Don't forget that using the ncurses backend, ncurses is still compiled in release mode, while only cursive will have unoptimized code.
In the case of termion, since it's all pure Rust code, it will also be compiled without optimizations.

In my case, I have flickering in both release and debug modes, when resizing out(resizing in is ok, in debug mode).
Note that I did not try to see if the flickering is present with other backends(don't want to install additional dependencies... that's why I love that there is the termion backend - I can compile a hello world application with Musl and strip it down to a 604K static binary).

@memoryruins
Copy link

Experiencing flicker in release mode with the termion-backend as well, specifically when the screen is updated often such as when typing into an EditView or scrolling. Noticeably less flicker than debug of course.

ncurses-backend and pancurses-backend did not flicker in release mode while testing the examples.

I absolutely love the Cursive api and am thrilled to see termion as a backend option, especially because of the support for Redox. Well done 🙏

@gyscos
Copy link
Owner Author

gyscos commented Dec 5, 2017

First, I'm very glad you like this library! Don't hesitate to give feedback on any part you feel deserves more work!

My main idea for now is to lock the standard output once instead of at every print. Unfortunately it doesn't look trivial, since StdoutLock needs to borrow Stdout, which means storing them in the termion backend would require a self-borrowing structure.

Maybe this can't be avoided. We already depend on owning_ref, I'll see if it can help there.

@HenryTheCat
Copy link
Contributor

Is there any news on this? On latest release (0.9.0 on MacOS) the flickering is still very bad, even in release builds, and even with single paints (with that, I mean without using set_fps to set a fixed frame-rate).

Is there anything needed on the termion side? I may try to contact the maintainers (I think it's currently under the Redox team) if it helps.

@gyscos
Copy link
Owner Author

gyscos commented Aug 30, 2018

No news yet - I need to find some time to focus on that.

In addition to locking stdout, another idea might be to buffer the whole screen, and flush it to the terminal after each step. Doing it without allocating everytime may need some more thinking.

We'll need to do this eventually to fix #100 (though interestingly, the issue doesn't affect termion).

@njskalski
Copy link
Contributor

I think Termion has already a double buffer mechanism:

https://docs.rs/termion/1.5.1/termion/screen/index.html

And if so, I would put double buffering into backend (by for instance adding method called "end_frame" or "swap_buffers"), not re-implement it on library level.

@gyscos is "Backend::clear" called only in begin of new frame, or has also other uses?

@FreeFull
Copy link

FreeFull commented Sep 8, 2018

@njskalski The screen switching is not a double-buffer mechanism. It is intended for full-screen programs such as Vim or Midnight Commander. As an example, when you start vim, it switches to the alternate screen, and when you quit or suspend vim, it switches back and the terminal shows its content from before you started vim.

@agavrilov
Copy link
Contributor

@gyscos I have created a buffering backend for any Cursive backend. See here. I used it with Termion and the flickering is gone

@gyscos
Copy link
Owner Author

gyscos commented Oct 24, 2018

Wow - awesome! Congratulations!

I'll have a look, but it may be a great workaround until we get a better buffering story inside Cursive itself - which might take a cue from your work! :)

Note: you may need to update the buffer size whenever the WindowResize event is sent.

@agavrilov
Copy link
Contributor

I'm checking the terminal size in 'Backend::clear' method and resize if necessary.

Let me know if you need any help with adding a buffering to Cursive

@gyscos
Copy link
Owner Author

gyscos commented Mar 1, 2019

I'll probably bring this caching system to the core of cursive, where it will apply to all backends.

In the meantime, I updated the termion backend to:

  • Access /dev/tty directly so stdin/stdout can be used for other things (well, almost, retrieving the terminal size still uses stdout for now)
  • Use buffered file io fall all input/output, so we don't need to lock on every print.

This brings the termion performance on par with the ncurses backend.

@vmedea
Copy link
Contributor

vmedea commented Oct 28, 2019

I'll probably bring this caching system to the core of cursive, where it will apply to all backends.

I suppose it would ideally be switched based on backend. This would definitely be nice to have for termion and crossterm. I've noticed the flicker as well.

For *ncurses and bearlibterm, which already do their own character cell buffering, it might increase the overhead.

I think Termion has already a double buffer mechanism:

Please don't use it for that 😓 The alternate screen—which is implemented by terminals, not by termion itself—is there to restore the state of the terminal after exiting an application.

@HenryTheCat
Copy link
Contributor

I know this issue is being worked on, but is there anything that users can do in the meantime to solve or mitigate the issue? With either termion or crossterm backends, I get a very noticeable flickering. I tried to batch calls to the Printer in the View::draw method of my Views, so that I would print a whole line at a time rather than a single character, but that didn't help at all (I have little understanding of the inner working of terminals).

@vmedea
Copy link
Contributor

vmedea commented Aug 13, 2020

know this issue is being worked on, but is there anything that users can do in the meantime to solve or mitigate the issue?

Yes, I'm using @agavrilov's cursive_buffered_backend in my own project to work around this. It performs similar kind of buffering that curses does, queuing up changes then sending them at once at refresh, instead of sending every little update directly to the terminal. That solves the issue for me without having to do anything besides initialize it at start of the program.

hrkfdn added a commit to hrkfdn/ncspot that referenced this issue Sep 11, 2022
This is reported to be occuring with the Cursive Termion backend as it redraws
the screen every time, resulting in flickering for some users.

Should be removed once Cursive has integrated this.

See also:
- gyscos/cursive#142
- gyscos/cursive#667

Fixes #934
yasuo-ozu pushed a commit to yasuo-ozu/rusty-man that referenced this issue May 7, 2023
With this patch, we replace cursive’s default ncurses backend with the
termion backend.  This has multiple reasons:
- The ncurses backend has safety issues, see [0].
- ncurses requires a pre-installed library and a C compiler, introducing
  additional build dependencies.  Termion is implemented in Rust only.
- ncurses does not work on Windows, while termion works in all terminals
  that support ANSI escape codes.

Per default, the termion backend does not buffer the output which may
cause flickering [1].  Therefore, we also use the
cursive_buffered_backend that buffers the output and fixes the
flickering problem.

[0] gyscos/cursive#488
[1] gyscos/cursive#142
azat added a commit to azat-archive/chdig that referenced this issue Oct 28, 2023
There are some issues with depeendency from the ncurses library, it does
not allows to compile chdig in a static binary (this could be done, but
requires some work), and this leads to a requirement for minimal glibc
version, recently I tried to run chdig on debian buster, and it fails:

    $ chdig
    chdig: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by chdig)
    chdig: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.29' not found (required by chdig)

    # apt-cache policy libc6
    libc6:
      Installed: 2.28-10+deb10u2
      Candidate: 2.28-10+deb10u2
      Version table:
     *** 2.28-10+deb10u2 500
            500 http://security.debian.org/debian-security buster/updates/main amd64 Packages
            100 /var/lib/dpkg/status
         2.28-10+deb10u1 500
            500 http://deb.debian.org/debian buster/main amd64 Packages

Last time I've tried other backends, they all experience flickering
issues [1], but, cursive_buffered_backend [2] - solves the problem!

  [1]: gyscos/cursive#142
  [2]: https://github.com/agavrilov/cursive_buffered_backend

Also I have to remove --mouse/--no-mouse, since for this the cursive
should be patched.
azat added a commit to azat-archive/chdig that referenced this issue Oct 28, 2023
There are some issues with depeendency from the ncurses library, it does
not allows to compile chdig in a static binary (this could be done, but
requires some work), and this leads to a requirement for minimal glibc
version, recently I tried to run chdig on debian buster, and it fails:

    $ chdig
    chdig: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by chdig)
    chdig: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.29' not found (required by chdig)

    # apt-cache policy libc6
    libc6:
      Installed: 2.28-10+deb10u2
      Candidate: 2.28-10+deb10u2
      Version table:
     *** 2.28-10+deb10u2 500
            500 http://security.debian.org/debian-security buster/updates/main amd64 Packages
            100 /var/lib/dpkg/status
         2.28-10+deb10u1 500
            500 http://deb.debian.org/debian buster/main amd64 Packages

Last time I've tried other backends, they all experience flickering
issues [1], but, cursive_buffered_backend [2] - solves the problem!

  [1]: gyscos/cursive#142
  [2]: https://github.com/agavrilov/cursive_buffered_backend

Also I have to remove --mouse/--no-mouse, since for this the cursive
should be patched.
azat added a commit to azat-archive/chdig that referenced this issue Oct 28, 2023
There are some issues with depeendency from the ncurses library, it does
not allows to compile chdig in a static binary (this could be done, but
requires some work), and this leads to a requirement for minimal glibc
version, recently I tried to run chdig on debian buster, and it fails:

    $ chdig
    chdig: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by chdig)
    chdig: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.29' not found (required by chdig)

    # apt-cache policy libc6
    libc6:
      Installed: 2.28-10+deb10u2
      Candidate: 2.28-10+deb10u2
      Version table:
     *** 2.28-10+deb10u2 500
            500 http://security.debian.org/debian-security buster/updates/main amd64 Packages
            100 /var/lib/dpkg/status
         2.28-10+deb10u1 500
            500 http://deb.debian.org/debian buster/main amd64 Packages

Last time I've tried other backends, they all experience flickering
issues [1], but, cursive_buffered_backend [2] - solves the problem!

  [1]: gyscos/cursive#142
  [2]: https://github.com/agavrilov/cursive_buffered_backend

Also I have to remove --mouse/--no-mouse, since for this the cursive
should be patched.
azat added a commit to azat/chdig that referenced this issue Oct 28, 2023
There are some issues with depeendency from the ncurses library, it does
not allows to compile chdig in a static binary (this could be done, but
requires some work), and this leads to a requirement for minimal glibc
version, recently I tried to run chdig on debian buster, and it fails:

    $ chdig
    chdig: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by chdig)
    chdig: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.29' not found (required by chdig)

    # apt-cache policy libc6
    libc6:
      Installed: 2.28-10+deb10u2
      Candidate: 2.28-10+deb10u2
      Version table:
     *** 2.28-10+deb10u2 500
            500 http://security.debian.org/debian-security buster/updates/main amd64 Packages
            100 /var/lib/dpkg/status
         2.28-10+deb10u1 500
            500 http://deb.debian.org/debian buster/main amd64 Packages

Last time I've tried other backends, they all experience flickering
issues [1], but, cursive_buffered_backend [2] - solves the problem!

  [1]: gyscos/cursive#142
  [2]: https://github.com/agavrilov/cursive_buffered_backend

Also I have to remove --mouse/--no-mouse, since for this the cursive
should be patched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants