Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache outline headers & ref count outline provider #210213

Merged
merged 5 commits into from
Apr 17, 2024

Conversation

DonJayamanne
Copy link
Contributor

For #209787

this._disposables.add(_configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(NotebookSetting.outlineShowMarkdownHeadersOnly) ||
e.affectsConfiguration(NotebookSetting.outlineShowCodeCells) ||
e.affectsConfiguration(NotebookSetting.outlineShowCodeCellSymbols) ||
e.affectsConfiguration(NotebookSetting.breadcrumbsShowCodeCells)
) {
this._recomputeState();
delayedRecompute();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debouncing in outline provider resulted in significant improvements
From 60s to run a cell to 2-3s.
(this was already fixed in a previous PR, but this now adds the same debouncing for typing in editor).

When ever we make changes in editor (typing), we trigger outline changes synchronously
As a result, ever key stroke results in outline calculation.
With a large notebook (100 markdown cells and each markdown cell having 10-20 lines), then it takes around 50ms to calculate the outline.
This is ignoring code cells in outline.

Thus every key stroke results in a 50ms delay in renderer.
Solution = debounce

getOrCreate(editor: INotebookEditor, target: OutlineTarget): IReference<NotebookCellOutlineProvider>
}

export class NotebookCellOutlineProviderFactory implements INotebookCellOutlineProviderFactory {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 outline providers are created.
Meaning each key stroke in cell editors results in outlines being calculated 3 times.
Assume we take 50ms to calculate it, then we spend 50+50+50ms in total for each keystroke

Now it will be only one calculation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you actually see the provider for the goto symbols being calculated on each keystroke? I thought that one was only called when you open that widget

Copy link
Contributor Author

@DonJayamanne DonJayamanne Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes,
Open the widget, and every keystroke will result in outline being calculated (3 times)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only called when you open that widget

Given the fact taht this is also used by other widgets, its possible it will re-compute it,
E.g. when the Sticky scroll feature is eanbled, we re-compute on every key stroke even if the outline widget is not visible.

const fullContent = cell.getText().substring(0, 10000);
for (const { depth, text } of getMarkdownHeadersInCell(fullContent)) {
const headers = cache?.alternativeId === cell.getAlternativeId() ? cache.headers : Array.from(getMarkdownHeadersInCell(fullContent));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This caching results in saving 50% of the time used to calculate outlines.
Down from 50ms to 26

I.e. this PR brings down the total time in keystokes from 150ms to 0 (when debounced) and when user stops typing, then we spend 20ms.

We should see some significant perf gains here.

}
}

private init() {
this.notebookOutline.init();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need to call init.

if (!this.compareStickyLineMaps(recompute, this.currentStickyLines)) {
this.updateContent(recompute);
}
}));

this._disposables.add(this.notebookEditor.onDidAttachViewModel(() => {
this.notebookOutline.init();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more calling of init

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fact init has been removed, it seemed to be a work around.

@DonJayamanne DonJayamanne marked this pull request as ready for review April 17, 2024 00:48
@vscodenpa vscodenpa added this to the April 2024 milestone Apr 17, 2024
@DonJayamanne DonJayamanne merged commit 9102848 into main Apr 17, 2024
6 checks passed
@DonJayamanne DonJayamanne deleted the outlineRefCollectionAndCachingHeaders branch April 17, 2024 02:51
@DonJayamanne
Copy link
Contributor Author

DonJayamanne commented Apr 17, 2024

VS Code Stable (typing around 20 chars in quick succession)

Screenshot 2024-04-18 at 01 37 24

Screenshot 2024-04-18 at 01 37 09

Screenshot 2024-04-18 at 01 02 17

VS Code OSS (typing around 40 chars in quick succession)

The changes are not yet in VS Code insiders.

Screenshot 2024-04-18 at 02 42 59

Duplicate event (before & after)

Screenshot 2024-04-18 at 01 23 00

Screenshot 2024-04-18 at 02 43 11

@microsoft microsoft locked and limited conversation to collaborators Jun 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants