docs/source/developer/performance.md
% Copyright (c) Jupyter Development Team.
% Distributed under the terms of the Modified BSD License.
A list windowing algorithm is implemented in a dedicated widget WindowedList provided by @jupyterlab/ui-components.
This widget will have a DOM structure like this:
% code::html % % <div class="jp-WindowedPanel-outer"> % <div class="jp-WindowedPanel-inner"> % <div class="jp-WindowedPanel-viewport"> % <!-- Here will be the list of items in the viewport --> % </div> % </div> % </div>
The reason for encapsulating the visible items in such tree comes from the need to position the current view correctly in a fake document that has the real height.
Performance analysis of notebook documents in JupyterLab point out to two main bottlenecks: editors style computation and rendered markdown with lots of math expressions. The best technique to alleviate those problems are to attach to the DOM only the cells in the viewport. However code cell outputs bring a huge constraint that their internal state is within the DOM node (e.g. the zoom level on a map view). So the outputs cannot be detached once displayed With those considerations in mind, here is the algorithm coded for the notebook windowing.
:::{note}
When initializing the view, the code cell outputs are scanned to detect if they contain
text/html output defining style and/or scripts elements. If they do, those
cells are rendered to ensure styles and JavaScript are applied as they may leak outside
their definition cell (e.g. injection of custom styles).
:::
When cell widgets are instantiated, their children are not created (i.e. the editor, the outputs,…) and they are not attached to the DOM. The view is updated on scroll events following:
Due to the code cells being kept in the DOM, we need to update the data attribute
data-windowed-list-index when the cells list changes. This is required to attach at the
correct position the cell when the viewport changes.
The list windowing algorithm is coded in a dedicated widget WindowedList. The notebook
extends it and uses a specialized layout to deal with code cells, NotebookWindowedLayout.
The code cell layout is also customized CodeCellLayout to keep the output area attached
but not the other children.
:::{warning} The current implementation does not handle iframe well. In Chrome, the iframe states are reset every time they leave and renter the viewport. In Firefox, it does not happen when scrolling comes from mouse scrolls. But the reset happens when jumping to a specific position that was out of viewport; e.g. searching for a word or navigating to a heading. :::
Each cell widget implements those three attributes:
isPlaceholder will be false if the cell has never been attached (and therefore have no children instantiated).ready returns a promise that resolves when a cell is fully instantiated. After that the editor and any children will exist.inViewport whether the cell is currently in viewport or not. You can listen to the signal inViewportChanged.The notebook widget has the following helper :
scrollToItem to scroll to a specific cell index. Like for scrolling an element into view, various mode are available.