textsearch.perf.integrationTest.ts 7.1 KB
Newer Older
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

8
import 'vs/workbench/parts/search/electron-browser/search.contribution'; // load contributions
9
import * as assert from 'assert';
10
import * as fs from 'fs';
11
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
J
Johannes Rieken 已提交
12
import { createSyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
B
Benjamin Pasero 已提交
13
import { INextEditorGroupsService } from 'vs/workbench/services/group/common/nextEditorGroupsService';
14
import { ISearchService, IQueryOptions } from 'vs/platform/search/common/search';
15
import { ITelemetryService, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
J
Johannes Rieken 已提交
16
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
B
Benjamin Pasero 已提交
17
import { INextEditorService } from 'vs/workbench/services/editor/common/nextEditorService';
18 19
import * as minimist from 'minimist';
import * as path from 'path';
J
Johannes Rieken 已提交
20 21
import { SearchService } from 'vs/workbench/services/search/node/searchService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
B
Benjamin Pasero 已提交
22
import { TestEnvironmentService, TestContextService, TestEditorService, TestEditorGroupsService } from 'vs/workbench/test/workbenchTestServices';
J
Johannes Rieken 已提交
23 24
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { TPromise } from 'vs/base/common/winjs.base';
25
import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
26
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
27
import { SimpleConfigurationService } from 'vs/editor/standalone/browser/simpleServices';
J
Johannes Rieken 已提交
28 29 30
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { IModelService } from 'vs/editor/common/services/modelService';
31

32
import { SearchModel } from 'vs/workbench/parts/search/common/searchModel';
33
import { QueryBuilder } from 'vs/workbench/parts/search/common/queryBuilder';
34

M
Matt Bierner 已提交
35
import * as event from 'vs/base/common/event';
36
import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
37
import { NullLogService, ILogService } from 'vs/platform/log/common/log';
38

39 40 41 42 43
declare var __dirname: string;

// Checkout sources to run against:
// git clone --separate-git-dir=testGit --no-checkout --single-branch https://chromium.googlesource.com/chromium/src testWorkspace
// cd testWorkspace; git checkout 39a7f93d67f7
44
// Run from repository root folder with (test.bat on Windows): ./scripts/test-int-mocha.sh --grep TextSearch.performance --timeout 500000 --testWorkspace <path>
45
suite.skip('TextSearch performance (integration)', () => {
46 47

	test('Measure', () => {
B
💄  
Benjamin Pasero 已提交
48
		if (process.env['VSCODE_PID']) {
49
			return undefined; // TODO@Rob find out why test fails when run from within VS Code
B
💄  
Benjamin Pasero 已提交
50 51
		}

52
		const n = 3;
53 54
		const argv = minimist(process.argv);
		const testWorkspaceArg = argv['testWorkspace'];
55
		const testWorkspacePath = testWorkspaceArg ? path.resolve(testWorkspaceArg) : __dirname;
56 57 58
		if (!fs.existsSync(testWorkspacePath)) {
			throw new Error(`--testWorkspace doesn't exist`);
		}
59 60

		const telemetryService = new TestTelemetryService();
61 62 63
		const configurationService = new SimpleConfigurationService();
		const instantiationService = new InstantiationService(new ServiceCollection(
			[ITelemetryService, telemetryService],
64
			[IConfigurationService, configurationService],
A
Alex Dima 已提交
65
			[IModelService, new ModelServiceImpl(null, configurationService)],
66
			[IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))],
B
Benjamin Pasero 已提交
67 68
			[INextEditorService, new TestEditorService()],
			[INextEditorGroupsService, new TestEditorGroupsService()],
69
			[IEnvironmentService, TestEnvironmentService],
70
			[IUntitledEditorService, createSyncDescriptor(UntitledEditorService)],
71 72
			[ISearchService, createSyncDescriptor(SearchService)],
			[ILogService, new NullLogService()]
73 74
		));

75
		const queryOptions: IQueryOptions = {
76 77
			maxResults: 2048
		};
78

79 80 81
		const searchModel: SearchModel = instantiationService.createInstance(SearchModel);
		function runSearch(): TPromise<any> {
			const queryBuilder: QueryBuilder = instantiationService.createInstance(QueryBuilder);
82
			const query = queryBuilder.text({ pattern: 'static_library(' }, [URI.file(testWorkspacePath)], queryOptions);
83 84 85 86 87 88 89 90 91 92 93 94 95 96

			// Wait for the 'searchResultsFinished' event, which is fired after the search() promise is resolved
			const onSearchResultsFinished = event.filterEvent(telemetryService.eventLogged, e => e.name === 'searchResultsFinished');
			event.once(onSearchResultsFinished)(onComplete);

			function onComplete(): void {
				try {
					const allEvents = telemetryService.events.map(e => JSON.stringify(e)).join('\n');
					assert.equal(telemetryService.events.length, 3, 'Expected 3 telemetry events, got:\n' + allEvents);

					const [firstRenderEvent, resultsShownEvent, resultsFinishedEvent] = telemetryService.events;
					assert.equal(firstRenderEvent.name, 'searchResultsFirstRender');
					assert.equal(resultsShownEvent.name, 'searchResultsShown');
					assert.equal(resultsFinishedEvent.name, 'searchResultsFinished');
97

98 99 100 101 102 103 104
					telemetryService.events = [];

					resolve(resultsFinishedEvent);
				} catch (e) {
					// Fail the runSearch() promise
					error(e);
				}
105
			}
106 107 108 109 110 111 112 113 114 115 116 117

			let resolve;
			let error;
			return new TPromise((_resolve, _error) => {
				resolve = _resolve;
				error = _error;

				// Don't wait on this promise, we're waiting on the event fired above
				searchModel.search(query).then(
					null,
					_error);
			});
118 119
		}

120 121
		const finishedEvents = [];
		return runSearch() // Warm-up first
122
			.then(() => {
123
				if (testWorkspaceArg) { // Don't measure by default
124
					let i = n;
125
					return (function iterate() {
126
						if (!i--) {
127
							return;
128
						}
129 130 131 132 133

						return runSearch()
							.then((resultsFinishedEvent: any) => {
								console.log(`Iteration ${n - i}: ${resultsFinishedEvent.data.duration / 1000}s`);
								finishedEvents.push(resultsFinishedEvent);
134 135
								return iterate();
							});
136
					})().then(() => {
137 138
						const totalTime = finishedEvents.reduce((sum, e) => sum + e.data.duration, 0);
						console.log(`Avg duration: ${totalTime / n / 1000}s`);
139
					});
140 141 142 143 144 145 146 147 148
				}
			});
	});
});

class TestTelemetryService implements ITelemetryService {
	public _serviceBrand: any;
	public isOptedIn = true;

J
Joao Moreno 已提交
149
	public events: any[] = [];
150

151 152
	private emitter = new event.Emitter<any>();

M
Matt Bierner 已提交
153
	public get eventLogged(): event.Event<any> {
154 155 156
		return this.emitter.event;
	}

157
	public publicLog(eventName: string, data?: any): TPromise<void> {
158 159 160
		const event = { name: eventName, data: data };
		this.events.push(event);
		this.emitter.fire(event);
161
		return TPromise.wrap<void>(null);
162 163 164
	}

	public getTelemetryInfo(): TPromise<ITelemetryInfo> {
165
		return TPromise.wrap({
166 167 168 169 170
			instanceId: 'someValue.instanceId',
			sessionId: 'someValue.sessionId',
			machineId: 'someValue.machineId'
		});
	}
171
}