chore - StopWatch sugar, make high-res the default, use globalThis, faster _now function (#185330)

* chore - StopWatch sugar, make high-res the default, use `globalThis`, faster `_now` function

* d'oh

* make layerscheck happy
This commit is contained in:
Johannes Rieken 2023-06-16 16:34:52 +02:00 committed by GitHub
parent e44d44a55e
commit e4324a5cb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 37 additions and 40 deletions

View file

@ -755,7 +755,7 @@ export class EventProfiling {
}
start(listenerCount: number): void {
this._stopWatch = new StopWatch(true);
this._stopWatch = new StopWatch();
this.listenerCount = listenerCount;
}

View file

@ -3,22 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { globals } from 'vs/base/common/platform';
// fake definition so that the valid layers check won't trip on this
declare const globalThis: { performance?: { now(): number } };
const hasPerformanceNow = (globals.performance && typeof globals.performance.now === 'function');
const hasPerformanceNow = (globalThis.performance && typeof globalThis.performance.now === 'function');
export class StopWatch {
private _highResolution: boolean;
private _startTime: number;
private _stopTime: number;
public static create(highResolution: boolean = true): StopWatch {
private readonly _now: () => number;
public static create(highResolution?: boolean): StopWatch {
return new StopWatch(highResolution);
}
constructor(highResolution: boolean) {
this._highResolution = hasPerformanceNow && highResolution;
constructor(highResolution?: boolean) {
this._now = hasPerformanceNow && highResolution === false ? Date.now : globalThis.performance!.now.bind(globalThis.performance);
this._startTime = this._now();
this._stopTime = -1;
}
@ -38,8 +40,4 @@ export class StopWatch {
}
return this._now() - this._startTime;
}
private _now(): number {
return this._highResolution ? globals.performance.now() : Date.now();
}
}

View file

@ -154,18 +154,18 @@ suite('SkipList', function () {
// init
const list = new SkipList<number, boolean>(cmp, max);
let sw = new StopWatch(true);
let sw = new StopWatch();
values.forEach(value => list.set(value, true));
sw.stop();
console.log(`[LIST] ${list.size} elements after ${sw.elapsed()}ms`);
let array: number[] = [];
sw = new StopWatch(true);
sw = new StopWatch();
values.forEach(value => array = insertArraySorted(array, value));
sw.stop();
console.log(`[ARRAY] ${array.length} elements after ${sw.elapsed()}ms`);
// get
sw = new StopWatch(true);
sw = new StopWatch();
const someValues = [...values].slice(0, values.size / 4);
someValues.forEach(key => {
const value = list.get(key); // find
@ -174,7 +174,7 @@ suite('SkipList', function () {
});
sw.stop();
console.log(`[LIST] retrieve ${sw.elapsed()}ms (${(sw.elapsed() / (someValues.length * 2)).toPrecision(4)}ms/op)`);
sw = new StopWatch(true);
sw = new StopWatch();
someValues.forEach(key => {
const idx = binarySearch(array, key, cmp); // find
console.assert(idx >= 0, '[ARRAY] must have ' + key);
@ -185,13 +185,13 @@ suite('SkipList', function () {
// insert
sw = new StopWatch(true);
sw = new StopWatch();
someValues.forEach(key => {
list.set(-key, false);
});
sw.stop();
console.log(`[LIST] insert ${sw.elapsed()}ms (${(sw.elapsed() / someValues.length).toPrecision(4)}ms/op)`);
sw = new StopWatch(true);
sw = new StopWatch();
someValues.forEach(key => {
array = insertArraySorted(array, -key);
});
@ -199,14 +199,14 @@ suite('SkipList', function () {
console.log(`[ARRAY] insert ${sw.elapsed()}ms (${(sw.elapsed() / someValues.length).toPrecision(4)}ms/op)`);
// delete
sw = new StopWatch(true);
sw = new StopWatch();
someValues.forEach(key => {
list.delete(key); // find
list.delete(-key); // miss
});
sw.stop();
console.log(`[LIST] delete ${sw.elapsed()}ms (${(sw.elapsed() / (someValues.length * 2)).toPrecision(4)}ms/op)`);
sw = new StopWatch(true);
sw = new StopWatch();
someValues.forEach(key => {
array = delArraySorted(array, key); // find
array = delArraySorted(array, -key); // miss

View file

@ -961,7 +961,7 @@ suite.skip('TST, perf', function () {
function perfTest(name: string, callback: Function) {
test(name, function () {
if (_profile) { console.profile(name); }
const sw = new StopWatch(true);
const sw = new StopWatch();
callback();
console.log(name, sw.elapsed());
if (_profile) { console.profileEnd(); }

View file

@ -143,7 +143,7 @@ export class EditorWorkerService extends Disposable implements IEditorWorkerServ
if (!canSyncModel(this._modelService, resource)) {
return Promise.resolve(edits); // File too large
}
const sw = StopWatch.create(true);
const sw = StopWatch.create();
const result = this._workerManager.withWorker().then(client => client.computeMoreMinimalEdits(resource, edits, pretty));
result.finally(() => this._logService.trace('FORMAT#computeMoreMinimalEdits', resource.toString(true), sw.elapsed()));
return Promise.race([result, timeout(1000).then(() => edits)]);
@ -158,7 +158,7 @@ export class EditorWorkerService extends Disposable implements IEditorWorkerServ
if (!canSyncModel(this._modelService, resource)) {
return Promise.resolve(edits); // File too large
}
const sw = StopWatch.create(true);
const sw = StopWatch.create();
const result = this._workerManager.withWorker().then(client => client.computeHumanReadableDiff(resource, edits,
{ ignoreTrimWhitespace: false, maxComputationTimeMs: 1000, computeMoves: false, })).catch((err) => {
onUnexpectedError(err);

View file

@ -67,7 +67,7 @@ export class WorkerBasedDocumentDiffProvider implements IDocumentDiffProvider, I
return c.result;
}
const sw = StopWatch.create(true);
const sw = StopWatch.create();
const result = await this.editorWorkerService.computeDiff(original.uri, modified.uri, options, this.diffAlgorithm);
const timeMs = sw.elapsed();

View file

@ -685,7 +685,7 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable {
public async textualSuggest(modelUrls: string[], leadingWord: string | undefined, wordDef: string, wordDefFlags: string): Promise<{ words: string[]; duration: number } | null> {
const sw = new StopWatch(true);
const sw = new StopWatch();
const wordDefRegExp = new RegExp(wordDef, wordDefFlags);
const seen = new Set<string>();

View file

@ -311,7 +311,7 @@ export class FoldingController extends Disposable implements IEditorContribution
if (!foldingModel) { // null if editor has been disposed, or folding turned off
return null;
}
const sw = new StopWatch(true);
const sw = new StopWatch();
const provider = this.getRangeProvider(foldingModel.textModel);
const foldingRegionPromise = this.foldingRegionPromise = createCancelablePromise(token => provider.compute(token));
return foldingRegionPromise.then(foldingRanges => {
@ -1269,4 +1269,3 @@ CommandsRegistry.registerCommand('_executeFoldingRangeProvider', async function
rangeProvider.dispose();
}
});

View file

@ -218,7 +218,7 @@ export async function provideSuggestionItems(
token: CancellationToken = CancellationToken.None
): Promise<CompletionItemModel> {
const sw = new StopWatch(true);
const sw = new StopWatch();
position = position.clone();
const word = model.getWordAtPosition(position);
@ -280,7 +280,7 @@ export async function provideSuggestionItems(
if (options.providerFilter.size > 0 && !options.providerFilter.has(_snippetSuggestSupport)) {
return;
}
const sw = new StopWatch(true);
const sw = new StopWatch();
const list = await _snippetSuggestSupport.provideCompletionItems(model, position, context, token);
onCompletionList(_snippetSuggestSupport, list, sw);
})();
@ -305,7 +305,7 @@ export async function provideSuggestionItems(
return;
}
try {
const sw = new StopWatch(true);
const sw = new StopWatch();
const list = await provider.provideCompletionItems(model, position, context, token);
didAddResult = onCompletionList(provider, list, sw) || didAddResult;
} catch (err) {

View file

@ -349,7 +349,7 @@ export class SuggestController implements IEditorContribution {
} else if (!isResolved) {
// async additional edits
const sw = new StopWatch(true);
const sw = new StopWatch();
let position: IPosition | undefined;
const docListener = model.onDidChangeContent(e => {

View file

@ -24,7 +24,7 @@ class ForceRetokenizeAction extends EditorAction {
}
const model = editor.getModel();
model.tokenization.resetTokenization();
const sw = new StopWatch(true);
const sw = new StopWatch();
model.tokenization.forceTokenization(model.getLineCount());
sw.stop();
console.log(`tokenization took ${sw.elapsed()}`);

View file

@ -49,7 +49,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
disposables.add(this._notebookService.registerNotebookSerializer(viewType, extension, {
options,
dataToNotebook: async (data: VSBuffer): Promise<NotebookData> => {
const sw = new StopWatch(true);
const sw = new StopWatch();
const dto = await this._proxy.$dataToNotebook(handle, data, CancellationToken.None);
const result = NotebookDto.fromNotebookDataDto(dto.value);
this._logService.trace(`[NotebookSerializer] dataToNotebook DONE after ${sw.elapsed()}ms`, {
@ -59,7 +59,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
return result;
},
notebookToData: (data: NotebookData): Promise<VSBuffer> => {
const sw = new StopWatch(true);
const sw = new StopWatch();
const result = this._proxy.$notebookToData(handle, new SerializableObjectWithBuffers(NotebookDto.toNotebookDataDto(data)), CancellationToken.None);
this._logService.trace(`[NotebookSerializer] notebookToData DONE after ${sw.elapsed()}`, {
viewType,

View file

@ -391,7 +391,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
const COUNT = 2;
let sum = 0;
for (let i = 0; i < COUNT; i++) {
const sw = StopWatch.create(true);
const sw = StopWatch.create();
await this._proxy.$acceptProcessRequestLatency(terminalId);
sw.stop();
sum += sw.elapsed();

View file

@ -982,7 +982,7 @@ class CompletionsAdapter {
const replaceRange = doc.getWordRangeAtPosition(pos) || new Range(pos, pos);
const insertRange = replaceRange.with({ end: pos });
const sw = new StopWatch(true);
const sw = new StopWatch();
const itemsOrList = await this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context));
if (!itemsOrList) {

View file

@ -84,7 +84,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider {
async provideCompletionItems(model: ITextModel, position: Position, context: CompletionContext): Promise<CompletionList> {
const sw = new StopWatch(true);
const sw = new StopWatch();
const languageId = this._getLanguageIdAtPosition(model, position);
const languageConfig = this._languageConfigurationService.getLanguageConfiguration(languageId);
const snippets = new Set(await this._snippets.getSnippets(languageId));

View file

@ -228,7 +228,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager {
let sum = 0;
for (let i = 0; i < COUNT; i++) {
const sw = StopWatch.create(true);
const sw = StopWatch.create();
await proxy.test_latency(i);
sw.stop();
sum += sw.elapsed();
@ -248,7 +248,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager {
for (let i = 0; i < buff.byteLength; i++) {
buff.writeUInt8(i, value);
}
const sw = StopWatch.create(true);
const sw = StopWatch.create();
await proxy.test_up(buff);
sw.stop();
return ExtensionHostManager._convert(SIZE, sw.elapsed());
@ -257,7 +257,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager {
private async _measureDown(proxy: IExtensionHostProxy): Promise<number> {
const SIZE = 10 * 1024 * 1024; // 10MB
const sw = StopWatch.create(true);
const sw = StopWatch.create();
await proxy.test_down(SIZE);
sw.stop();
return ExtensionHostManager._convert(SIZE, sw.elapsed());

View file

@ -39,7 +39,7 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker {
public async detectLanguage(uri: string, langBiases: Record<string, number> | undefined, preferHistory: boolean, supportedLangs?: string[]): Promise<string | undefined> {
const languages: string[] = [];
const confidences: number[] = [];
const stopWatch = new StopWatch(true);
const stopWatch = new StopWatch();
const documentTextSample = this.getTextForDetection(uri);
if (!documentTextSample) { return; }