Skip to content

LP Renderer

Nilay Majorwar edited this page Feb 19, 2022 · 1 revision

The Renderer

The Renderer is simply a React component responsible for displaying the runtime state obtained from the language engine in a visually user-friendly way for visualisation and debugging purposes.

It receives a single prop state: RS | null. On every execution step, this prop changes to the value obtained from the language engine for the step executed. null is passed when there is no ongoing execution, on which you can show some placeholder message.

If you have some experience with React and CSS, this is usually a straightforward task. Ideally you shouldn't need any third-party libraries - try to keep it simple. There are some points related to performance you must take special care of.

Performance requirements

Imagine Esolang Park running on the minimum execution interval, i.e. 5ms. Here's what happens on each iteration of the execution cycle:

  1. The execution controller calls your engine and sends result of the execution step.
  2. The main thread receives this result and apart from other updates, passes the RS field in props to your React component.
  3. Your React component re-renders to show the new state.

Now, if your React component takes more than 5ms to re-render, the main thread will still be busy at the time the next update comes in and thus there will be a delay in consuming this new update. This delay keeps building up, and 5 seconds later there are over 2000 updates pending for processing by the main thread.

The one big way this destroys the debugger's utility is that now if the user pauses execution, the 2000 pending updates will still be processed and the execution will pause some seconds later - by which time the user's point of interest in the program execution is gone. Basically, poor performance of the React component can lead to a significant de-sync between what's shown on the screen and where the execution really is. Fortunately, it's not very difficult to ensure good performance.

Profiling your component

The React DevTools browser extension has a built-in profiler available to measure the performance of your React component. Open the profiler tab in your browser devtools and find the "Start profiling" button (don't click it yet).

Now on Esolang Park, run a program in your esolang that lasts for at least 5 seconds. Right after execution starts, click on the "Start profiling" button and then click it again a couple of seconds later, to see the flamegraph chart. Notice that the majority of the chart is greyed out. This is because apart from the renderer component, no other component is rendered at execution time.

The topmost yellow bar (labelled RendererWrapperComponent) represents your renderer component. Click on it to see the time taken by your component to render on each execution step.

Try to avoid BlueprintJS components

Esolang Park uses BlueprintJS for UI components used in the IDE. While the library is very good for general UI purposes, most components are nowhere near performant enough for a 5ms execution interval. Due to this reason, whenever you require a UI component for your renderer, consider a hand-written component first.

BlueprintJS exposes its color palette as a JS export called Colors from @blueprintjs/core. Using this palette and checking the colors used by BlueprintJS in its components, it's quite easy to create components that fit in with the IDE and are super-performant as well.

For an example, see the SimpleTag component used in the Shakespeare renderer, which is at least 10x more performant than BlueprintJS's Tag component and still looks quite okay in place. Most of your purposes while implementing the renderer component can probably do with such hand-built components.

Clone this wiki locally