codeworld
codeworld copied to clipboard
Redesign console input and output using xtermjs
Shared Program: https://code.world/haskell#PpcrjDqEzZaVUG0a4_0b_Kg
Description
If a console program prints a lot of output, it gets very slow. The reason seems to be that instead of just appending the content to the existing output element, the entire last output element is rebuilt from scratch. This looks to be part of the collapsible UI code that was built for error reporting, but inexplicably includes output as well.
We should special-case normal output from programs, so that it is appended directly without rebuilding the element. If we could remove the collapsible UI at the same time, that's even better!
I believe I fixed the issue. Please let me know if there is anything else to be accomplished here.
This change was merged, but I'm still seeing the problem. In the linked program, profiling says that out of 15 seconds of running time, 12 of them were spent on rendering. It might be better than it was because we're not replacing the entire content each time, but it's still not good.
I don't know how to proceed here, so I'll just leave this open to track the issue.
For comparison, running the same generated code in node.js requires 9 seconds total, and the console scrolls smoothly.
It may be that just appending to a div isn't the right way to implement the console output. Given that I also want to hook up stdin eventually, perhaps something like https://xtermjs.org/ would be a good replacement. It's not clear to me how this would work with error messages; perhaps one should add terminal divs just like one adds log sections now?
Just an idea. No idea if it would work.
According to my findings, appending text to an element isn't an issue. Yes, there is a difference in speed when comparing techniques (with jQuery's append()
being the fastest in my tests), but it's imperceptible. The real bottleneck is scrolling to the bottom of the block every time the message is printed. This causes forced layout reflow and leads to stutter and jank. Here's how things look without auto-scrolling:
At the moment, I can't think of a way to alleviate this problem. I tried scrolling to the bottom first and doing the rest afterwards, and using a constant value for the Y position - neither did the trick.
The idea of using xtermjs is definitely growing on me. It should avoid this, since appending to the console wouldn't change elements at all, but rather just lead the component to rerender its view (which is does with WebGL, strangely). But it's probably best to put this on a back burner for a while, and work on clearer goals.
If the transition to xtermjs is made, should possibly try to handle #762 at the same time.
Further thoughts on this:
I think, in retrospect, mixing error messages and output was a bad idea. Instead, I believe the output area should switch to a tab UI, where there is one tab called "Console" that shows stdout and stdin, and a second tab called "Problems" that shows warnings and errors. When Inspect mode is on, it would be a third tab. All three tabs, in fact, are optional. If the program has no warnings or errors, doesn't touch stdin or stdout, and Inspect mode is off, then there would be no tabs open at all. This wouldn't be a big change from the existing behavior, where the output window is blank.
@alphalambda FYI, it looks like I already reached the conclusion we discussed today, on Sep 21. So this is in my queue, but I don't have any promises on time frame.