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

notebook open optimizations #13488

Merged
merged 8 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 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,10 @@ 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 { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
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 +88,6 @@ export default new ContainerModule(bind => {
bind(NotebookCellModelFactory).toFactory(ctx => (props: NotebookCellModelProps) =>
createNotebookCellModelContainer(ctx.container, props).get(NotebookCellModel)
);

rebind(MonacoTextModelService).to(NotebookMonacoTextModelService).inSingletonScope();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// *****************************************************************************
// 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 { 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 extends MonacoTextModelService {
jonah-iden marked this conversation as resolved.
Show resolved Hide resolved

protected readonly cellmodels = new ReferenceCollection<string, MonacoEditorModel>(
uri => this.loadModel(new URI(uri))
jonah-iden marked this conversation as resolved.
Show resolved Hide resolved
);

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;
}
}
6 changes: 5 additions & 1 deletion packages/notebook/src/browser/service/notebook-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ 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';

export const NotebookProvider = Symbol('notebook provider');

Expand Down Expand Up @@ -52,6 +53,9 @@ export class NotebookService implements Disposable {
@inject(NotebookCellModelFactory)
protected notebookCellModelFactory: (props: NotebookCellModelProps) => NotebookCellModel;

@inject(MonacoTextModelService)
protected textModelService: NotebookMonacoTextModelService;

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

Expand Down Expand Up @@ -111,7 +115,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 @@ -28,6 +28,7 @@ import {
} from '../../common';
import { NotebookCellOutputsSplice } from '../notebook-types';
import { NotebookCellOutputModel } from './notebook-cell-output-model';
import { NotebookMonacoTextModelService } from '../service/notebook-monaco-text-model-service';

export const NotebookCellModelFactory = Symbol('NotebookModelFactory');
export type NotebookCellModelFactory = (props: NotebookCellModelProps) => NotebookCellModel;
Expand Down Expand Up @@ -103,7 +104,7 @@ export class NotebookCellModel implements NotebookCell, Disposable {
@inject(NotebookCellModelProps)
protected readonly props: NotebookCellModelProps;
@inject(MonacoTextModelService)
protected readonly textModelService: MonacoTextModelService;
protected readonly textModelService: NotebookMonacoTextModelService;

get outputs(): NotebookCellOutputModel[] {
return this._outputs;
Expand Down Expand Up @@ -277,7 +278,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 @@ -116,7 +116,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 @@ -91,21 +91,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,29 @@
// 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 { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
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 +49,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(MonacoTextModelService) 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 @@ -357,6 +357,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 @@ -236,6 +236,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
Loading