Replies: 16 comments
-
I posted a follow up on #160118 to help you recreate the issue. I'm not sure this is the correct diagnosis as the terminal is not flooded with data. |
Beta Was this translation helpful? Give feedback.
-
@Tyriar I not sure if that went out of focus too fast - @0x00C5 states several times, that the terminal has lit. no data to process in between. So the terminal might not even be the root of the additional processing time? |
Beta Was this translation helpful? Give feedback.
-
Yeah I was looking at another issue as well, must have gotten mixed up. The proposal still stands though, I've been thinking about a battery/low-power mode for VS Code for a while which would cap FPS to 10 fps or something. |
Beta Was this translation helpful? Give feedback.
-
Personally I don't see why a terminal would need more than 10 FPS. I'd prefer speed of build over real-time terminal output (plus, building is less resource intensive than reflowing the terminal). Perhaps when animation frame comes around, maybe only run the terminal update every 5th iteration with a flag to enable full 60 FPS for those who need it. |
Beta Was this translation helpful? Give feedback.
-
Well a terminal is mostly about interactivity, thus high FPS is needed to not expose a high input latency. Typically input lags are perceivable >30ms, and fast typers might even recognize latencies >20ms. Now the browser engines cap screen refresh at 60 FPS, which translates to ~16ms for screen update cycles. That leaves ~4ms for everything else, which is almost impossible to stay below (note that TEs are dumb terminals, thus have to send the input to the PTY, which sends the characters back for echoing). And that "backend-line" is esp. long for xterm.js due to several layers being involved (nodejs buffers, websocket, browser event loop). And for ssh connections things get even worse. TL;DR: I cannot agree with you - high FPS is a must for a TE to avoid sluggish typing response. The opposite happens, if app side creates tons of output (e.g. a very noisy compiler). Here the output latency is not as important anymore (the user cannot read along at all anymore), so it is a good idea to scale down FPS on purpose to save some processing time. |
Beta Was this translation helpful? Give feedback.
-
@jerch I was actually thinking we would do this by keeping the screen update after an input event as it is today, but throttling the rest. This would avoid the input latency problem while saving frames. Whether this applies to scrolling I'm not sure as that's one of the bigger things that determines how smooth or laggy as app feels. @0x00C5 on why the terminal can do 60+ fps (up to 240 on my monitor 👀), I've used terminals that cap the frame rate and they just don't feel as nice to use imo. The amount of data needed to have a real difference is quite large anyway and rarely noticed in practice. A higher FPS also gives you additional visual feedback of how much output the command produced. The hope is to someday move parsing to a worker (#1515) which would mean that rendering would only contend with other things in the application, such as the editor in VS Code. Part of the reason for the slowdown in parsing is because it's sharing the thread we need to split the parsing task up to keep the app responsive, which adds a bunch of overhead. That's not a problem if it's done in a worker. |
Beta Was this translation helpful? Give feedback.
-
@jerch I agree with you. I didn't mean to imply the terminals frame rate should be permanently capped. An immediate response to input is absolutely necessary and should be high priority and not throttled. I was referring to enabling a low FPS when building, even if the program floods the console (which I assume would be fairly rare in practice), it could give the compiler a higher priority but still be responsive. @Tyriar sure I meant lowering the frame rate during build time which (I would imagine) shouldn't affect the overall responsiveness if the terminal spit out lines/chunks every 80ms verses 16ms. You'd still see lots of data coming thru at 12 FPS. Granted, I'm not sure what a good frame rate would be or what the tradeoffs would be, but I wouldn't mind a option that capped the frame rate during build time or changed the weight of the build vs output. |
Beta Was this translation helpful? Give feedback.
-
@0x00C5 Well proper FPS is a very old discussion. Citing some details from Wikipedia: Old filmmakers of the area of silent films typically shot in only 16-20 FPS, while a later industry standard specced it at 24 FPS (note that much earlier Edison already propagated 48Hz as optimal for the human eye, but this was too cost intensive, therefore most projectors doubled the 24 FPS frames). TV did the interlacing trick, staying pretty close to that 24 value, but faking higher refresh rates by updating half images (at 50 or 60 Hz). For a while computer CRTs did the same, but since it was very stressful for the users, they raises refresh rates pretty quick, often in multiples of 30 or 60 Hz (thus 90, 120 or even 240 Hz, depending on resolution, as the beam had to get across the phosphor dots in that time), and later switched to progressive scanning. Long story short - it seems 24 FPS is the bare minimum, but already stressful to watch for a longer time. To ensure updates get through in time we again have the sampling theorem issue, which tells us to get at least at 48 FPS. You can check this for yourself with an old webcam, they typically would send images at 30 FPS - thats sluggish as hell. Now a terminal is not about watching a movie - true. Still users will have the same "sluggish feeling" from low terminal refresh rate, as thats a matter of perception and not of the content presented. Whether 30 FPS is still okish for most peeps in a terminal - idk. Anything below 30 FPS is certainly not, as content will break into stop-and-go. Whether xterm.js would benefit from FPS halving (from 60 to 30):
Summary: |
Beta Was this translation helpful? Give feedback.
-
Reducing battery usage was one of my motivations for this topic, I probably won't bother looking into it unless VS Code as a whole has a push for such a low power mode |
Beta Was this translation helpful? Give feedback.
-
@jerch All your points are true. Since the Terminal is a line-oriented dump of text that scrolls by a fixed amount per line, I wouldn't think it requires the same refresh rate as the DOM to catch pixel-by-pixel scrolling. I suggested 12 FPS simply because terminal output is typically chunky in practice and can tolerate some gitter, unlike a video. The best FPS to aim for would probably be best demonstrated with an example to see the tradeoffs specific to terminal output. I read an article while back [1] that showed the same GIF rendering at 8 to 60 FPS. Perhaps simulating the xterm output with a GIF at different frame rates would be a better way to see where an acceptable threshold would be? Maybe 12 FPS would be OK? Maybe 30? I dunno. The article mentions all modern browsers cannot render gifs at 60 FPS or greater. Personally, I'd prefer a configuration option to customize xterm's OUTPUT FPS in steps of 6 FPS to 60 FPS (or whatever) which in turn can be used by different vscode modes. For example, a "low power mode" (like @Tyriar mentioned) which could cap INPUT and OUTPUT FPS. Or a "build mode" (like I want) which could cap the OUTPUT FPS during builds. Note I define OUTPUT FPS as xterm waiting for its prompt to be yielded back. [1] https://wunkolo.github.io/post/2020/02/buttery-smooth-10fps/ |
Beta Was this translation helpful? Give feedback.
-
@0x00C5 Oh thats an interesting test with the black circle. For me only 33 & 50 FPS dont show any tearing/shadowing, all slower ones have bad artefacts here. |
Beta Was this translation helpful? Give feedback.
-
I would think skipping a couple animation frames to lower the FPS wouldn't cause any tearing/shadowing as the browser should still sync it at the proper interval. It will obviously get more choppy/jittery the frame rate gets lower, but it *may* not induce artifacts. |
Beta Was this translation helpful? Give feedback.
-
No clue how the browser deals with that - I clearly see "shadows" of circle parts with the slower FPS, but not for 33+. Maybe some interference pattern from gif FPS to display FPS, idk. |
Beta Was this translation helpful? Give feedback.
-
I've gotten used to my 144 and 240 FPS monitors and I can definitely detect the difference between 60 and 144, 144-240 not so much. You're probably right that there is a sweet spot though since it's not a circle animating where we could cap FPS, however that doesn't actually help us that much in increasing throughput. Reducing FPS helps by potentially reducing battery usage, but as for increasing throughput I don't think we can't do much. Regardless of an FPS target, we need to ensure the embedding application window remains responsive, which means we still need to limit parsing to <= a single frame (we target ~16ms for 60 FPS currently). The real fix for throughput is the worker discussion in #1515 |
Beta Was this translation helpful? Give feedback.
-
Also FYI this is inaccurate now FYI: |
Beta Was this translation helpful? Give feedback.
-
That's my understanding too as most of the gifs frames won't be in phase with the refresh rate of the screen. I think af avoids those issues.
Maybe. There might be some wiggle room. I have no idea what the sweet spot would be without some experimentation. I personally wouldn't mind the embedded terminal yielding to the parser or an option to due so like I mentioned earlier. I think the terminal is unique in that it can get away with a lower fps when dumping its output (regardless of the amount of output). |
Beta Was this translation helpful? Give feedback.
-
See microsoft/vscode#160118
Beta Was this translation helpful? Give feedback.
All reactions