vscode原始碼分析【三】程式的啟動邏輯,效能問題的追蹤

liulun發表於2019-06-18

第一篇: vscode原始碼分析【一】從原始碼執行vscode
第二篇:vscode原始碼分析【二】程式的啟動邏輯,第一個視窗是如何建立的

啟動追蹤

程式碼檔案:src\main.js
如果指定了特定的啟動引數:trace
vscode會在啟動之初,執行下面的程式碼:

const contentTracing = require('electron').contentTracing;
		const traceOptions = {
			categoryFilter: args['trace-category-filter'] || '*',
			traceOptions: args['trace-options'] || 'record-until-full,enable-sampling'
		};
		contentTracing.startRecording(traceOptions, () => onReady());

這段程式碼的主要目的是:從Chromium的內容模組收集跟蹤資料,以查詢效能瓶頸和程式執行緩慢的操作。
注意,這個操作只能在app.ready事件觸發之後才能執行; startRecoding會非同步請求所有子程式開始執行追蹤操作;
一旦所有子程式都確認了主程式的請求,主程式就會執行startRecoding的回撥方法;

結束追蹤

在視窗成功啟動之後,vscode結束了效能問題的追蹤(如果30秒視窗還沒啟動,那麼也會結束效能問題的追蹤)
程式碼檔案:vs\code\electron-main\app.ts(在上一篇博文中,啟動第一個視窗,也是在這裡執行的)

const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient));

stopTracingEventually方法的程式碼為:

	private stopTracingEventually(windows: ICodeWindow[]): void {
		this.logService.info(`Tracing: waiting for windows to get ready...`);

		let recordingStopped = false;
		const stopRecording = (timeout: boolean) => {
			if (recordingStopped) {
				return;
			}

			recordingStopped = true; // only once

			contentTracing.stopRecording(join(homedir(), `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`), path => {
				if (!timeout) {
					if (this.windowsMainService) {
						this.windowsMainService.showMessageBox({
							type: 'info',
							message: localize('trace.message', "Successfully created trace."),
							detail: localize('trace.detail', "Please create an issue and manually attach the following file:\n{0}", path),
							buttons: [localize('trace.ok', "Ok")]
						}, this.windowsMainService.getLastActiveWindow());
					}
				} else {
					this.logService.info(`Tracing: data recorded (after 30s timeout) to ${path}`);
				}
			});
		};

		// Wait up to 30s before creating the trace anyways
		const timeoutHandle = setTimeout(() => stopRecording(true), 30000);

		// Wait for all windows to get ready and stop tracing then
		Promise.all(windows.map(window => window.ready())).then(() => {
			clearTimeout(timeoutHandle);
			stopRecording(false);
		});
	}

子程式會快取跟蹤資料,一般不會把跟蹤資料傳送給主程式(避免傳送資料再造成效能消耗),
所以,結束跟蹤也是主程式非同步地要求所有子程式持久化跟蹤資料的。
跟蹤結束後,會執行stopRecording的回撥函式。
在這裡會顯示一個提示框,提示使用者效能追蹤的結果;(如果超了30秒,那麼就只記日誌了)

 

 

相關文章