From a346a70c6fdf3d2e2df16cbb86dabb5b796a2a7d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 7 Jul 2021 13:50:41 +0200 Subject: [PATCH] storage - do not warm up sqlite on load of another workspace (#127421) --- .../electron-main/lifecycleMainService.ts | 16 +---- .../electron-main/storageMainService.ts | 5 +- .../electron-main/storageMainService.test.ts | 4 +- .../platform/windows/electron-main/window.ts | 60 ++++++++++--------- .../platform/windows/electron-main/windows.ts | 43 ++++++++++++- .../electron-main/windowsMainService.ts | 4 +- 6 files changed, 84 insertions(+), 48 deletions(-) diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts index f8442834981..d78bfe44ffd 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts @@ -8,7 +8,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IStateMainService } from 'vs/platform/state/electron-main/state'; import { Event, Emitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { ICodeWindow, LoadReason, UnloadReason } from 'vs/platform/windows/electron-main/windows'; import { handleVetos } from 'vs/platform/lifecycle/common/lifecycle'; import { isMacintosh, isWindows } from 'vs/base/common/platform'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; @@ -20,18 +20,6 @@ import { cwd } from 'vs/base/common/process'; export const ILifecycleMainService = createDecorator('lifecycleMainService'); -export const enum LoadReason { - LOAD = 1, - RELOAD = 2 -} - -export const enum UnloadReason { - CLOSE = 1, - QUIT = 2, - RELOAD = 3, - LOAD = 4 -} - export interface IWindowLoadEvent { window: ICodeWindow; workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined; @@ -363,7 +351,7 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe this.windowCounter++; // Window Will Load - windowListeners.add(window.onWillLoad(e => this._onWillLoadWindow.fire({ window, workspace: e.workspace, reason: e.isReload ? LoadReason.RELOAD : LoadReason.LOAD }))); + windowListeners.add(window.onWillLoad(e => this._onWillLoadWindow.fire({ window, workspace: e.workspace, reason: e.reason }))); // Window Before Closing: Main -> Renderer const win = assertIsDefined(window.win); diff --git a/src/vs/platform/storage/electron-main/storageMainService.ts b/src/vs/platform/storage/electron-main/storageMainService.ts index 7312e3b7a28..10a9a0d195c 100644 --- a/src/vs/platform/storage/electron-main/storageMainService.ts +++ b/src/vs/platform/storage/electron-main/storageMainService.ts @@ -7,9 +7,10 @@ import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { ILifecycleMainService, LifecycleMainPhase, LoadReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; +import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILogService } from 'vs/platform/log/common/log'; import { GlobalStorageMain, IStorageMain, IStorageMainOptions, WorkspaceStorageMain } from 'vs/platform/storage/electron-main/storageMain'; +import { LoadReason } from 'vs/platform/windows/electron-main/windows'; import { IEmptyWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; export const IStorageMainService = createDecorator('storageMainService'); @@ -61,7 +62,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic // Workspace Storage: Warmup when related window with workspace loads this._register(this.lifecycleMainService.onWillLoadWindow(async e => { if (e.workspace) { - if (e.reason === LoadReason.RELOAD) { + if (e.reason !== LoadReason.INITIAL) { return; // TODO@bpasero mitigate https://github.com/microsoft/vscode/issues/127421 } diff --git a/src/vs/platform/storage/test/electron-main/storageMainService.test.ts b/src/vs/platform/storage/test/electron-main/storageMainService.test.ts index 091de0aa8bf..07681e2b2c9 100644 --- a/src/vs/platform/storage/test/electron-main/storageMainService.test.ts +++ b/src/vs/platform/storage/test/electron-main/storageMainService.test.ts @@ -12,10 +12,10 @@ import { currentSessionDateStorageKey, firstSessionDateStorageKey, instanceStora import { IStorageChangeEvent, IStorageMain, IStorageMainOptions } from 'vs/platform/storage/electron-main/storageMain'; import { generateUuid } from 'vs/base/common/uuid'; import { IS_NEW_KEY } from 'vs/platform/storage/common/storage'; -import { ILifecycleMainService, LifecycleMainPhase, ShutdownEvent, UnloadReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; +import { ILifecycleMainService, LifecycleMainPhase, ShutdownEvent } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { Emitter, Event } from 'vs/base/common/event'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -import { ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { ICodeWindow, UnloadReason } from 'vs/platform/windows/electron-main/windows'; import { Promises } from 'vs/base/common/async'; import product from 'vs/platform/product/common/product'; import { IProductService } from 'vs/platform/product/common/productService'; diff --git a/src/vs/platform/windows/electron-main/window.ts b/src/vs/platform/windows/electron-main/window.ts index 303fa089d41..1062fda4e76 100644 --- a/src/vs/platform/windows/electron-main/window.ts +++ b/src/vs/platform/windows/electron-main/window.ts @@ -17,7 +17,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { WindowMinimumSize, IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; import { Disposable } from 'vs/base/common/lifecycle'; import { browserCodeLoadingCacheStrategy, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; -import { defaultWindowState, ICodeWindow, ILoadEvent, IWindowState, WindowError, WindowMode } from 'vs/platform/windows/electron-main/windows'; +import { defaultWindowState, ICodeWindow, ILoadEvent, IWindowState, LoadReason, WindowError, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; @@ -35,6 +35,7 @@ import { FileAccess, Schemas } from 'vs/base/common/network'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol'; +import { RunOnceScheduler } from 'vs/base/common/async'; export interface IWindowCreationOptions { state: IWindowState; @@ -92,22 +93,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { //#endregion - private hiddenTitleBarStyle: boolean | undefined; - private showTimeoutHandle: NodeJS.Timeout | undefined; - private windowState: IWindowState; - private currentMenuBarVisibility: MenuBarVisibility | undefined; - private representedFilename: string | undefined; - private documentEdited: boolean | undefined; - - private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[] = []; - - private marketplaceHeadersPromise: Promise; - - private readonly touchBarGroups: TouchBarSegmentedControl[] = []; - - private currentHttpProxy: string | undefined = undefined; - private currentNoProxy: string | undefined = undefined; + //#region Properties private _id: number; get id(): number { return this._id; } @@ -124,13 +111,10 @@ export class CodeWindow extends Disposable implements ICodeWindow { get remoteAuthority(): string | undefined { return this.currentConfig?.remoteAuthority; } - private pendingLoadConfig: INativeWindowConfiguration | undefined; - private currentConfig: INativeWindowConfiguration | undefined; get config(): INativeWindowConfiguration | undefined { return this.currentConfig; } - private readonly configObjectUrl = this._register(this.protocolMainService.createIPCObjectUrl()); - + private hiddenTitleBarStyle: boolean | undefined; get hasHiddenTitleBarStyle(): boolean { return !!this.hiddenTitleBarStyle; } get isExtensionDevelopmentHost(): boolean { return !!(this.currentConfig?.extensionDevelopmentPath); } @@ -139,6 +123,27 @@ export class CodeWindow extends Disposable implements ICodeWindow { get isExtensionDevelopmentTestFromCli(): boolean { return this.isExtensionDevelopmentHost && this.isExtensionTestHost && !this.currentConfig?.debugId; } + //#endregion + + + private readonly windowState: IWindowState; + private currentMenuBarVisibility: MenuBarVisibility | undefined; + + private representedFilename: string | undefined; + private documentEdited: boolean | undefined; + + private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[] = []; + + private readonly touchBarGroups: TouchBarSegmentedControl[] = []; + + private marketplaceHeadersPromise: Promise; + private currentHttpProxy: string | undefined = undefined; + private currentNoProxy: string | undefined = undefined; + + private readonly configObjectUrl = this._register(this.protocolMainService.createIPCObjectUrl()); + private pendingLoadConfig: INativeWindowConfiguration | undefined; + private wasLoaded = false; + constructor( config: IWindowCreationOptions, @ILogService private readonly logService: ILogService, @@ -762,20 +767,25 @@ export class CodeWindow extends Disposable implements ICodeWindow { 'vs/code/electron-browser/workbench/workbench.html', require ).toString(true)); + // Remember that we did load + const wasLoaded = this.wasLoaded; + this.wasLoaded = true; + // Make window visible if it did not open in N seconds because this indicates an error // Only do this when running out of sources and not when running tests if (!this.environmentMainService.isBuilt && !this.environmentMainService.extensionTestsLocationURI) { - this.showTimeoutHandle = setTimeout(() => { + this._register(new RunOnceScheduler(() => { if (this._win && !this._win.isVisible() && !this._win.isMinimized()) { this._win.show(); this.focus({ force: true }); this._win.webContents.openDevTools(); } - }, 10000); + + }, 10000)).schedule(); } // Event - this._onWillLoad.fire({ workspace: configuration.workspace, isReload: options.isReload ?? false }); + this._onWillLoad.fire({ workspace: configuration.workspace, reason: options.isReload ? LoadReason.RELOAD : wasLoaded ? LoadReason.LOAD : LoadReason.INITIAL }); } private updateConfiguration(configuration: INativeWindowConfiguration, options: ILoadOptions): void { @@ -1367,10 +1377,6 @@ export class CodeWindow extends Disposable implements ICodeWindow { override dispose(): void { super.dispose(); - if (this.showTimeoutHandle) { - clearTimeout(this.showTimeoutHandle); - } - this._win = null!; // Important to dereference the window object to allow for GC } } diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index ffa205f0762..3fd639f044e 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -15,6 +15,47 @@ import { Rectangle, BrowserWindow, WebContents } from 'electron'; import { IDisposable } from 'vs/base/common/lifecycle'; import { CancellationToken } from 'vs/base/common/cancellation'; +export const enum LoadReason { + + /** + * The window is loaded for the first time. + */ + INITIAL = 1, + + /** + * The window is loaded into a different workspace context. + */ + LOAD, + + /** + * The window is reloaded. + */ + RELOAD +} + +export const enum UnloadReason { + + /** + * The window is closed. + */ + CLOSE = 1, + + /** + * All windows unload because the application quits. + */ + QUIT, + + /** + * The window is reloaded. + */ + RELOAD, + + /** + * The window is loaded into a different workspace context. + */ + LOAD +} + export const enum OpenContext { // opening when running from the command line @@ -62,7 +103,7 @@ export const enum WindowMode { export interface ILoadEvent { workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined; - isReload: boolean; + reason: LoadReason; } export interface ICodeWindow extends IDisposable { diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index d5f26fada5c..8a775d273d1 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -17,14 +17,14 @@ import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { IStateMainService } from 'vs/platform/state/electron-main/state'; import { CodeWindow } from 'vs/platform/windows/electron-main/window'; import { app, BrowserWindow, MessageBoxOptions, nativeTheme, WebContents } from 'electron'; -import { ILifecycleMainService, UnloadReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; +import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration, INativeOpenFileRequest } from 'vs/platform/windows/common/windows'; import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder'; import { Event, Emitter } from 'vs/base/common/event'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows'; +import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IOpenEmptyConfiguration, OpenContext, UnloadReason } from 'vs/platform/windows/electron-main/windows'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import { IWorkspaceIdentifier, hasWorkspaceFileExtension, IRecent, isWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';