Skip to content

Commit

Permalink
notebook open optimizations (#13488)
Browse files Browse the repository at this point in the history
* only initialize notebbok cell editor when in viewport

Signed-off-by: Jonah Iden <[email protected]>

* optimzied notebook loading time by bulk creating notebook cell editor text models

Signed-off-by: Jonah Iden <[email protected]>

* remove measurement

Signed-off-by: Jonah Iden <[email protected]>

* add document for cell when creating new one

Signed-off-by: Jonah Iden <[email protected]>

* review changes

* rebase build fixe

Signed-off-by: Jonah Iden <[email protected]>

* create unmaged models for monacto text model service

Signed-off-by: Jonah Iden <[email protected]>

---------

Signed-off-by: Jonah Iden <[email protected]>
  • Loading branch information
jonah-iden authored Mar 28, 2024
1 parent f41a764 commit 2c61f6c
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 21 deletions.
10 changes: 9 additions & 1 deletion packages/monaco/src/browser/monaco-text-model-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,15 @@ export class MonacoTextModelService implements ITextModelService {
return this._models.acquire(raw.toString());
}

protected async loadModel(uri: URI): Promise<MonacoEditorModel> {
/**
* creates a model which is not saved by the model service.
* this will therefore also not be created on backend side.
*/
createUnmangedModel(raw: monaco.Uri | URI): Promise<MonacoEditorModel> {
return this.loadModel(new URI(raw.toString()));
}

async loadModel(uri: URI): Promise<MonacoEditorModel> {
await this.editorPreferences.ready;
const resource = await this.resourceProvider(uri);
const model = await (await this.createModel(resource)).load();
Expand Down
5 changes: 4 additions & 1 deletion packages/notebook/src/browser/notebook-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ import { NotebookKernelHistoryService } from './service/notebook-kernel-history-
import { NotebookEditorWidgetService } from './service/notebook-editor-widget-service';
import { NotebookRendererMessagingService } from './service/notebook-renderer-messaging-service';
import { NotebookColorContribution } from './contributions/notebook-color-contribution';
import { NotebookMonacoTextModelService } from './service/notebook-monaco-text-model-service';

export default new ContainerModule(bind => {
export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(NotebookColorContribution).toSelf().inSingletonScope();
bind(ColorContribution).toService(NotebookColorContribution);

Expand Down Expand Up @@ -86,4 +87,6 @@ export default new ContainerModule(bind => {
bind(NotebookCellModelFactory).toFactory(ctx => (props: NotebookCellModelProps) =>
createNotebookCellModelContainer(ctx.container, props).get(NotebookCellModel)
);

bind(NotebookMonacoTextModelService).toSelf().inSingletonScope();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// *****************************************************************************
// Copyright (C) 2024 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************

import { ReferenceCollection, URI, Reference, Event } from '@theia/core';
import { inject, injectable } from '@theia/core/shared/inversify';
import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
import { NotebookModel } from '../view-model/notebook-model';

/**
* special service for creating monaco textmodels for notebook cells.
* Its for optimization purposes since there is alot of overhead otherwise with calling the backend to create a document for each cell and other smaller things.
*/
@injectable()
export class NotebookMonacoTextModelService {

@inject(MonacoTextModelService)
protected readonly monacoTextModelService: MonacoTextModelService;

protected readonly cellmodels = new ReferenceCollection<string, MonacoEditorModel>(
uri => this.monacoTextModelService.createUnmangedModel(new URI(uri))
);

getOrCreateNotebookCellModelReference(uri: URI): Promise<Reference<MonacoEditorModel>> {
return this.cellmodels.acquire(uri.toString());
}

async createTextModelsForNotebook(notebook: NotebookModel): Promise<void> {
await Promise.all(notebook.cells.map(cell => this.getOrCreateNotebookCellModelReference(cell.uri)));
}

get onDidCreateNotebookCellModel(): Event<MonacoEditorModel> {
return this.cellmodels.onDidCreate;
}
}
10 changes: 5 additions & 5 deletions packages/notebook/src/browser/service/notebook-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import { BinaryBuffer } from '@theia/core/lib/common/buffer';
import { NotebookData, TransientOptions } from '../../common';
import { NotebookModel, NotebookModelFactory, NotebookModelProps } from '../view-model/notebook-model';
import { FileService } from '@theia/filesystem/lib/browser/file-service';
import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
import { NotebookCellModel, NotebookCellModelFactory, NotebookCellModelProps } from '../view-model/notebook-cell-model';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { NotebookMonacoTextModelService } from './notebook-monaco-text-model-service';
import { CellEditOperation } from '../notebook-types';

export const NotebookProvider = Symbol('notebook provider');
Expand Down Expand Up @@ -51,15 +51,15 @@ export class NotebookService implements Disposable {
@inject(FileService)
protected fileService: FileService;

@inject(MonacoTextModelService)
protected modelService: MonacoTextModelService;

@inject(NotebookModelFactory)
protected notebookModelFactory: (props: NotebookModelProps) => NotebookModel;

@inject(NotebookCellModelFactory)
protected notebookCellModelFactory: (props: NotebookCellModelProps) => NotebookCellModel;

@inject(NotebookMonacoTextModelService)
protected textModelService: NotebookMonacoTextModelService;

protected willUseNotebookSerializerEmitter = new Emitter<string>();
readonly onWillUseNotebookSerializer = this.willUseNotebookSerializerEmitter.event;

Expand Down Expand Up @@ -119,7 +119,7 @@ export class NotebookService implements Disposable {
this.notebookModels.set(resource.uri.toString(), model);
// Resolve cell text models right after creating the notebook model
// This ensures that all text models are available in the plugin host
await Promise.all(model.cells.map(e => e.resolveTextModel()));
this.textModelService.createTextModelsForNotebook(model);
this.didAddNotebookDocumentEmitter.fire(model);
return model;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import { Disposable, DisposableCollection, Emitter, Event, URI } from '@theia/core';
import { inject, injectable, interfaces, postConstruct } from '@theia/core/shared/inversify';
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
import {
CellKind, NotebookCellCollapseState, NotebookCellInternalMetadata,
NotebookCellMetadata, CellOutput, CellData, CellOutputItem
} from '../../common';
import { NotebookCellOutputsSplice } from '../notebook-types';
import { NotebookMonacoTextModelService } from '../service/notebook-monaco-text-model-service';
import { NotebookCellOutputModel } from './notebook-cell-output-model';

export const NotebookCellModelFactory = Symbol('NotebookModelFactory');
Expand Down Expand Up @@ -105,8 +105,9 @@ export class NotebookCellModel implements NotebookCell, Disposable {

@inject(NotebookCellModelProps)
protected readonly props: NotebookCellModelProps;
@inject(MonacoTextModelService)
protected readonly textModelService: MonacoTextModelService;

@inject(NotebookMonacoTextModelService)
protected readonly textModelService: NotebookMonacoTextModelService;

get outputs(): NotebookCellOutputModel[] {
return this._outputs;
Expand Down Expand Up @@ -290,7 +291,7 @@ export class NotebookCellModel implements NotebookCell, Disposable {
return this.textModel;
}

const ref = await this.textModelService.createModelReference(this.uri);
const ref = await this.textModelService.getOrCreateNotebookCellModelReference(this.uri);
this.textModel = ref.object;
this.textModel.onDidChangeContent(e => {
this.props.source = e.model.getText();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class CellEditor extends React.Component<CellEditorProps, {}> {
override render(): React.ReactNode {
return <div className='theia-notebook-cell-editor' onResize={this.handleResize} id={this.props.cell.uri.toString()}
ref={container => this.setContainer(container)} style={{ height: this.editor ? undefined : this.estimateHeight() }}>
</div>;
</div >;
}

}
4 changes: 4 additions & 0 deletions packages/plugin-ext/src/main/browser/documents-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { dispose } from '../../common/disposable-util';
import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
import * as monaco from '@theia/monaco-editor-core';
import { TextDocumentChangeReason } from '../../plugin/types-impl';
import { NotebookDocumentsMainImpl } from './notebooks/notebook-documents-main';

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
Expand Down Expand Up @@ -90,6 +91,7 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {

constructor(
editorsAndDocuments: EditorsAndDocumentsMain,
notebookDocuments: NotebookDocumentsMainImpl,
private readonly modelService: EditorModelService,
rpc: RPCProtocol,
private editorManager: EditorManager,
Expand All @@ -105,6 +107,8 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
this.toDispose.push(editorsAndDocuments.onDocumentRemove(documents => documents.forEach(this.onModelRemoved, this)));
this.toDispose.push(modelService.onModelModeChanged(this.onModelChanged, this));

this.toDispose.push(notebookDocuments.onDidAddNotebookCellModel(this.onModelAdded, this));

this.toDispose.push(modelService.onModelSaved(m => {
this.proxy.$acceptModelSaved(m.textEditorModel.uri);
}));
Expand Down
8 changes: 5 additions & 3 deletions packages/plugin-ext/src/main/browser/main-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,23 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container

const editorsAndDocuments = new EditorsAndDocumentsMain(rpc, container);

const notebookDocumentsMain = new NotebookDocumentsMainImpl(rpc, container);
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN, notebookDocumentsMain);

const modelService = container.get(EditorModelService);
const editorManager = container.get(EditorManager);
const openerService = container.get<OpenerService>(OpenerService);
const shell = container.get(ApplicationShell);
const untitledResourceResolver = container.get(UntitledResourceResolver);
const languageService = container.get(MonacoLanguages);
const documentsMain = new DocumentsMainImpl(editorsAndDocuments, modelService, rpc, editorManager, openerService, shell, untitledResourceResolver, languageService);
const documentsMain = new DocumentsMainImpl(editorsAndDocuments, notebookDocumentsMain, modelService, rpc,
editorManager, openerService, shell, untitledResourceResolver, languageService);
rpc.set(PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN, documentsMain);

rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOKS_MAIN, new NotebooksMainImpl(rpc, container, commandRegistryMain));
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_RENDERERS_MAIN, new NotebookRenderersMainImpl(rpc, container));
const notebookEditorsMain = new NotebookEditorsMainImpl(rpc, container);
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_EDITORS_MAIN, notebookEditorsMain);
const notebookDocumentsMain = new NotebookDocumentsMainImpl(rpc, container);
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN, notebookDocumentsMain);
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_AND_EDITORS_MAIN, new NotebooksAndEditorsMain(rpc, container, notebookDocumentsMain, notebookEditorsMain));
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_KERNELS_MAIN, new NotebookKernelsMainImpl(rpc, container));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,28 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************

import { DisposableCollection } from '@theia/core';
import { DisposableCollection, Event } from '@theia/core';
import { URI, UriComponents } from '@theia/core/lib/common/uri';
import { interfaces } from '@theia/core/shared/inversify';
import { NotebookModelResolverService } from '@theia/notebook/lib/browser';
import { NotebookModel } from '@theia/notebook/lib/browser/view-model/notebook-model';
import { NotebookCellsChangeType } from '@theia/notebook/lib/common';
import { NotebookMonacoTextModelService } from '@theia/notebook/lib/browser/service/notebook-monaco-text-model-service';
import { MAIN_RPC_CONTEXT, NotebookCellsChangedEventDto, NotebookDataDto, NotebookDocumentsExt, NotebookDocumentsMain } from '../../../common';
import { RPCProtocol } from '../../../common/rpc-protocol';
import { NotebookDto } from './notebook-dto';
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';

export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {

private readonly disposables = new DisposableCollection();
protected readonly disposables = new DisposableCollection();

private readonly proxy: NotebookDocumentsExt;
private readonly documentEventListenersMapping = new Map<string, DisposableCollection>();
protected readonly proxy: NotebookDocumentsExt;
protected readonly documentEventListenersMapping = new Map<string, DisposableCollection>();

private readonly notebookModelResolverService: NotebookModelResolverService;
protected readonly notebookModelResolverService: NotebookModelResolverService;

protected notebookMonacoTextModelService: NotebookMonacoTextModelService;

constructor(
rpc: RPCProtocol,
Expand All @@ -44,6 +48,11 @@ export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {
this.disposables.push(this.notebookModelResolverService.onDidChangeDirty(model => this.proxy.$acceptDirtyStateChanged(model.uri.toComponents(), model.isDirty())));
this.disposables.push(this.notebookModelResolverService.onDidSaveNotebook(e => this.proxy.$acceptModelSaved(e)));

this.notebookMonacoTextModelService = container.get(NotebookMonacoTextModelService) as NotebookMonacoTextModelService;
}

get onDidAddNotebookCellModel(): Event<MonacoEditorModel> {
return this.notebookMonacoTextModelService.onDidCreateNotebookCellModel;
}

dispose(): void {
Expand Down
12 changes: 12 additions & 0 deletions packages/plugin-ext/src/plugin/notebook/notebook-document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,18 @@ export class NotebookDocument implements Disposable {
const extCell = new Cell(this, this.editorsAndDocuments, cell);
if (!initialization) {
addedCellDocuments.push(Cell.asModelAddData(this.apiNotebook, cell));
this.editorsAndDocuments.$acceptEditorsAndDocumentsDelta({
addedDocuments: [
{
uri: cell.uri,
versionId: 1,
lines: cell.source,
EOL: cell.eol,
modeId: '',
isDirty: false
}
]
});
}
return extCell;
});
Expand Down
13 changes: 12 additions & 1 deletion packages/plugin-ext/src/plugin/notebook/notebooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class NotebooksExtImpl implements NotebooksExt {
rpc: RPCProtocol,
commands: CommandRegistryExt,
private textDocumentsAndEditors: EditorsAndDocumentsExtImpl,
private textDocuments: DocumentsExtImpl
private textDocuments: DocumentsExtImpl,
) {
this.notebookProxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.NOTEBOOKS_MAIN);
this.notebookDocumentsProxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN);
Expand Down Expand Up @@ -242,6 +242,17 @@ export class NotebooksExtImpl implements NotebooksExt {
this.documents.get(uri.toString())?.dispose();
this.documents.set(uri.toString(), document);

this.textDocumentsAndEditors.$acceptEditorsAndDocumentsDelta({
addedDocuments: modelData.cells.map(cell => ({
uri: cell.uri,
versionId: 1,
lines: cell.source,
EOL: cell.eol,
modeId: '',
isDirty: false
}))
});

this.onDidOpenNotebookDocumentEmitter.fire(document.apiNotebook);
}
}
Expand Down

0 comments on commit 2c61f6c

Please sign in to comment.