Skip to content

Commit 201401d

Browse files
authored
Sends telemetry when a line is slow to tokenize. (microsoft#187835)
Fixes microsoft/vscode-internalbacklog#4454
1 parent b92a1b8 commit 201401d

File tree

5 files changed

+29
-17
lines changed

5 files changed

+29
-17
lines changed

src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate
5757
private _currentTokenColorMap: string[] | null = null;
5858
private readonly _workerHost = this._instantiationService.createInstance(
5959
TextMateWorkerHost,
60-
(timeMs, languageId, sourceExtensionId, lineLength) => this.reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength, true)
60+
(timeMs, languageId, sourceExtensionId, lineLength, isRandomSample) => this.reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength, true, isRandomSample)
6161
);
6262

6363
constructor(
@@ -291,9 +291,10 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate
291291
r.containsEmbeddedLanguages,
292292
(textModel, tokenStore) => this._workerHost.createBackgroundTokenizer(textModel, tokenStore, maxTokenizationLineLength),
293293
() => this._configurationService.getValue<boolean>('editor.experimental.asyncTokenizationVerification'),
294-
(timeMs, lineLength) => {
295-
this.reportTokenizationTime(timeMs, languageId, r.sourceExtensionId, lineLength, false);
296-
}
294+
(timeMs, lineLength, isRandomSample) => {
295+
this.reportTokenizationTime(timeMs, languageId, r.sourceExtensionId, lineLength, false, isRandomSample);
296+
},
297+
true,
297298
);
298299
tokenization.onDidEncounterLanguage((encodedLanguageId) => {
299300
if (!this._encounteredLanguages[encodedLanguageId]) {
@@ -377,7 +378,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate
377378
}
378379
}
379380

380-
public reportTokenizationTime(timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number, fromWorker: boolean): void {
381+
public reportTokenizationTime(timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number, fromWorker: boolean, isRandomSample: boolean): void {
381382
// 50 events per hour (one event has a low probability)
382383
if (TextMateTokenizationFeature.reportTokenizationTimeCounter > 50) {
383384
// Don't flood telemetry with too many events
@@ -396,6 +397,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate
396397
lineLength: number;
397398
fromWorker: boolean;
398399
sourceExtensionId: string | undefined;
400+
isRandomSample: boolean;
399401
}, {
400402
owner: 'hediet';
401403

@@ -404,6 +406,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate
404406
lineLength: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'To relate the performance to the line length' };
405407
fromWorker: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'To figure out if this line was tokenized sync or async' };
406408
sourceExtensionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'To figure out which extension contributed the grammar' };
409+
isRandomSample: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'To figure out if this is a random sample or measured because of some other condition.' };
407410

408411
comment: 'This event gives insight about the performance certain grammars.';
409412
}>('editor.tokenizedLine', {
@@ -412,6 +415,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate
412415
lineLength,
413416
fromWorker,
414417
sourceExtensionId,
418+
isRandomSample,
415419
});
416420
}
417421
}

src/vs/workbench/services/textMate/browser/tokenizationSupport/textMateTokenizationSupport.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ export class TextMateTokenizationSupport extends Disposable implements ITokeniza
2020
private readonly _grammar: IGrammar,
2121
private readonly _initialState: StateStack,
2222
private readonly _containsEmbeddedLanguages: boolean,
23-
private readonly _createBackgroundTokenizer?: (textModel: ITextModel, tokenStore: IBackgroundTokenizationStore) => IBackgroundTokenizer | undefined,
24-
private readonly _backgroundTokenizerShouldOnlyVerifyTokens: () => boolean = () => false,
25-
private readonly _reportTokenizationTime?: (timeMs: number, lineLength: number) => void,
23+
private readonly _createBackgroundTokenizer: ((textModel: ITextModel, tokenStore: IBackgroundTokenizationStore) => IBackgroundTokenizer | undefined) | undefined,
24+
private readonly _backgroundTokenizerShouldOnlyVerifyTokens: () => boolean,
25+
private readonly _reportTokenizationTime: (timeMs: number, lineLength: number, isRandomSample: boolean) => void,
26+
private readonly _reportSlowTokenization: boolean,
2627
) {
2728
super();
2829
}
@@ -47,12 +48,15 @@ export class TextMateTokenizationSupport extends Disposable implements ITokeniza
4748
}
4849

4950
public tokenizeEncoded(line: string, hasEOL: boolean, state: StateStack): EncodedTokenizationResult {
50-
const shouldMeasure = this._reportTokenizationTime && (Math.random() * 10_000 < 1);
51+
const isRandomSample = Math.random() * 10_000 < 1;
52+
const shouldMeasure = this._reportSlowTokenization || isRandomSample;
5153
const sw = shouldMeasure ? new StopWatch(true) : undefined;
5254
const textMateResult = this._grammar.tokenizeLine2(line, state, 500);
5355
if (shouldMeasure) {
5456
const timeMS = sw!.elapsed();
55-
this._reportTokenizationTime!(timeMS, line.length);
57+
if (isRandomSample || timeMS > 32) {
58+
this._reportTokenizationTime!(timeMS, line.length, isRandomSample);
59+
}
5660
}
5761

5862
if (textMateResult.stoppedEarly) {

src/vs/workbench/services/textMate/browser/worker/textMate.worker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ export class TextMateTokenizationWorker {
136136
this._host.setTokensAndStates(resource, versionId, tokens, stateDeltas);
137137
}
138138

139-
public reportTokenizationTime(timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number): void {
140-
this._host.reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength);
139+
public reportTokenizationTime(timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number, isRandomSample: boolean): void {
140+
this._host.reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength, isRandomSample);
141141
}
142142

143143
// #endregion

src/vs/workbench/services/textMate/browser/worker/textMateWorkerModel.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,12 @@ export class TextMateWorkerModel extends MirrorTextModel {
9898
if (r.grammar) {
9999
const tokenizationSupport = new TokenizationSupportWithLineLimit(
100100
this._encodedLanguageId,
101-
new TextMateTokenizationSupport(r.grammar, r.initialState, false, undefined, undefined,
102-
(timeMs, lineLength) => { this._worker.reportTokenizationTime(timeMs, languageId, r.sourceExtensionId, lineLength); }),
101+
new TextMateTokenizationSupport(r.grammar, r.initialState, false, undefined, () => false,
102+
(timeMs, lineLength, isRandomSample) => {
103+
this._worker.reportTokenizationTime(timeMs, languageId, r.sourceExtensionId, lineLength, isRandomSample);
104+
},
105+
false
106+
),
103107
this._maxTokenizationLineLength
104108
);
105109
this._tokenizationStateStore = new TokenizerWithStateStore(this._lines.length, tokenizationSupport);

src/vs/workbench/services/textMate/browser/workerHost/textMateWorkerHost.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class TextMateWorkerHost implements IDisposable {
3838
private _grammarDefinitions: IValidGrammarDefinition[] = [];
3939

4040
constructor(
41-
private readonly _reportTokenizationTime: (timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number) => void,
41+
private readonly _reportTokenizationTime: (timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number, isRandomSample: boolean) => void,
4242
@IExtensionResourceLoaderService private readonly _extensionResourceLoaderService: IExtensionResourceLoaderService,
4343
@IModelService private readonly _modelService: IModelService,
4444
@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
@@ -204,8 +204,8 @@ export class TextMateWorkerHost implements IDisposable {
204204
}
205205
}
206206

207-
public reportTokenizationTime(timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number): void {
208-
this._reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength);
207+
public reportTokenizationTime(timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number, isRandomSample: boolean): void {
208+
this._reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength, isRandomSample);
209209
}
210210

211211
// #endregion

0 commit comments

Comments
 (0)