DEV Community

Alexey Boyko
Alexey Boyko

Posted on

JavaScript. How to Make a Blazingly Fast Multithreaded Data Grid for 1,000,000 Rows. Part 1/2: The Nuances of Working with DOM

Demo | GitHub

Figure 1. Data Grid with 1,000,000 rowsFigure 1. Data Grid with 1,000,000 rows

Fast Data Grid Features:

  • Incredibly Fast
  • Multithreaded
  • Only 523 Lines of Code
  • No Dependencies
  • Vanilla JavaScript

Try scrolling and searching through 1,000,000 rows - Fast Data Grid.

In this article I will list the nuances of working with DOM. About multithreading in the next article.

The smaller the DOM, the better. Changing the contents of a DIV is faster than deleting a DIV and creating a new one.

The browser is slow in rendering a large DOM tree. The browser won't render 1,000,000 lines of 20 px height at all - the maximum height of a DIV in Chrome is 15,000,000 px. The fewer HTML elements, the better.

Fast Data Grid adds as many rows to the DOM as will fit on the screen.

const rowsCount = Math.ceil(viewPortHeight / rowHeight);
Enter fullscreen mode Exit fullscreen mode


Listing 1. Counting how many lines fit on the screen

When new data needs to be output, the row DIVs are reused. New data is written to the same DIVs. Changing the contents of a DIV is faster than deleting a DIV and creating a new one.

When scrolling, the position of the DIV rows is calculated using JavaScript.

Maximum DIV height is 15,000,000 px

To make the scroll work, Fast Data Grid makes a big DIV. The scroll event is attached to this DIV. The scroll event handler calculates the position of the row DIVs.

Figure 2. Large DIV for scrollingFigure 2. Large DIV for scrolling

If the total height of the rows is more than 15,000,000 px, then the row DIVs should scroll faster than the big DIV. When the big DIV scrolls to the end -> the row DIVs should also scroll to the end.

When scrolling DIV rows, a coefficient must be applied.

const scrollYKoef =
    // if {allRowsHeight} > 15 million -> we have to applay koef on scroll
    // if {allRowsHeight} <= 15 million -> {scrollYKoef} = 1
    (allRowsHeight - viewPortHeight) / (scrolHeight - viewPortHeight);


listen(scrollOverlayDiv, 'scroll', /** @param {Event & {target:HTMLDivElement}} evt */ evt => {
    const scrollTop = evt.target.scrollTop * scrollYKoef;
    rowsDiv.style.transform = `translateY(${scrollTop}px)`;
});
Enter fullscreen mode Exit fullscreen mode


Listing 2. Using the coefficient when scrolling

CSS transform translate is faster than CSS top

When scrolling, the position is set via transform translate. CSS transform translate is faster than CSS top.

<!-- transform faster-->
<div style="transform: translateY(-16px);"></div>

<!-- than top -->
<div style="top: -16px;"></div>
Enter fullscreen mode Exit fullscreen mode


Listing 3. CSS transform translate is faster than CSS top

Read DOM first, then modify DOM. It's bad to read DOM after modification

The browser displays frames on the monitor like this:
First, JavaScript is processed, then styles are calculated, then layout, then rendering.

Figure 3. Standard order of operations when outputting a frame to the monitorFigure 3. Standard order of operations when outputting a frame to the monitor

If the standard order is not violated, the browser will render the frame as quickly as possible.

At the beginning of the cycle, the DOM parameters are already calculated and correspond to the parameters of the previous frame. For example, box.offsetHeight is already calculated at the beginning of the cycle. But if you change the DOM and then read the DOM -> the browser will have to break the standard order. It will be necessary to calculate the layout again.

box.classList.add('super-big');

// Gets the height of the box in pixels and logs it out:
console.log(box.offsetHeight);
Enter fullscreen mode Exit fullscreen mode


Listing 4. Modifying DOM before reading DOM. Bad. Leads to layout thrashing.

Excessive recalculation of Layout is called “layout thrashing”.

A visual demonstration of how modifying the DOM before reading slows down the browser:
https://wilsonpage.github.io/fastdom/examples/animation.html

Great article on the topic:
Avoid large, complex layouts and layout thrashing | Articles | web.dev.

Self-promotion

I make the most convenient flowchart editor DGRM.net.
It is also the most convenient service for business: Excel + business process diagrams.

Give stars on GitHub.

Top comments (0)