Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4ce9098

Browse files
petebacondarwinAndrewKushnir
authored andcommitted
perf(ngcc): store the position of SegmentMarkers to avoid unnecessary computation (#36027)
Previously, calculations related to the position of and difference between SegmentMarkers required extensive computation based around the line, line start positions and columns of each segment. PR Close #36027
1 parent a0fa63b commit 4ce9098

File tree

4 files changed

+165
-163
lines changed

4 files changed

+165
-163
lines changed

packages/compiler-cli/ngcc/src/sourcemaps/segment_marker.ts

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
export interface SegmentMarker {
1717
readonly line: number;
1818
readonly column: number;
19+
readonly position: number;
1920
next: SegmentMarker|undefined;
2021
}
2122

@@ -26,20 +27,7 @@ export interface SegmentMarker {
2627
* and zero if they are at the same position.
2728
*/
2829
export function compareSegments(a: SegmentMarker, b: SegmentMarker): number {
29-
return a.line === b.line ? a.column - b.column : a.line - b.line;
30-
}
31-
32-
/**
33-
* Compute the difference between two segment markers in a source file.
34-
*
35-
* @param startOfLinePositions the position of the start of each line of content of the source file
36-
* where we are computing the difference
37-
* @param a the start marker
38-
* @param b the end marker
39-
* @returns the number of characters between the two segments `a` and `b`
40-
*/
41-
export function segmentDiff(startOfLinePositions: number[], a: SegmentMarker, b: SegmentMarker) {
42-
return startOfLinePositions[b.line] - startOfLinePositions[a.line] + b.column - a.column;
30+
return a.position - b.position;
4331
}
4432

4533
/**
@@ -51,19 +39,19 @@ export function segmentDiff(startOfLinePositions: number[], a: SegmentMarker, b:
5139
* @param offset the number of character to offset by.
5240
*/
5341
export function offsetSegment(
54-
startOfLinePositions: number[], marker: SegmentMarker, offset: number) {
42+
startOfLinePositions: number[], marker: SegmentMarker, offset: number): SegmentMarker {
5543
if (offset === 0) {
5644
return marker;
5745
}
5846

5947
let line = marker.line;
60-
const newPos = startOfLinePositions[line] + marker.column + offset;
61-
while (line < startOfLinePositions.length - 1 && startOfLinePositions[line + 1] <= newPos) {
48+
const position = marker.position + offset;
49+
while (line < startOfLinePositions.length - 1 && startOfLinePositions[line + 1] <= position) {
6250
line++;
6351
}
64-
while (line > 0 && startOfLinePositions[line] > newPos) {
52+
while (line > 0 && startOfLinePositions[line] > position) {
6553
line--;
6654
}
67-
const column = newPos - startOfLinePositions[line];
68-
return {line, column, next: undefined};
55+
const column = position - startOfLinePositions[line];
56+
return {line, column, position, next: undefined};
6957
}

packages/compiler-cli/ngcc/src/sourcemaps/source_file.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {removeComments, removeMapFileComments} from 'convert-source-map';
99
import {SourceMapMappings, SourceMapSegment, decode, encode} from 'sourcemap-codec';
1010
import {AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system';
1111
import {RawSourceMap} from './raw_source_map';
12-
import {SegmentMarker, compareSegments, offsetSegment, segmentDiff} from './segment_marker';
12+
import {SegmentMarker, compareSegments, offsetSegment} from './segment_marker';
1313

1414
export function removeSourceMapComments(contents: string): string {
1515
return removeMapFileComments(removeComments(contents)).replace(/\n\n$/, '\n');
@@ -89,7 +89,7 @@ export class SourceFile {
8989
* source files with no transitive source maps.
9090
*/
9191
private flattenMappings(): Mapping[] {
92-
const mappings = parseMappings(this.rawMap, this.sources);
92+
const mappings = parseMappings(this.rawMap, this.sources, this.startOfLinePositions);
9393
ensureOriginalSegmentLinks(mappings);
9494
const flattenedMappings: Mapping[] = [];
9595
for (let mappingIndex = 0; mappingIndex < mappings.length; mappingIndex++) {
@@ -277,8 +277,7 @@ export function mergeMappings(generatedSource: SourceFile, ab: Mapping, bc: Mapp
277277
// segment-marker" of B->C (4*): `1 - 4 = -3`.
278278
// Since it is negative we must increment the "generated segment-marker" with `3` to give [3,2].
279279

280-
const diff =
281-
segmentDiff(ab.originalSource.startOfLinePositions, ab.originalSegment, bc.generatedSegment);
280+
const diff = compareSegments(bc.generatedSegment, ab.originalSegment);
282281
if (diff > 0) {
283282
return {
284283
name,
@@ -303,7 +302,8 @@ export function mergeMappings(generatedSource: SourceFile, ab: Mapping, bc: Mapp
303302
* in the `sources` parameter.
304303
*/
305304
export function parseMappings(
306-
rawMap: RawSourceMap | null, sources: (SourceFile | null)[]): Mapping[] {
305+
rawMap: RawSourceMap | null, sources: (SourceFile | null)[],
306+
generatedSourceStartOfLinePositions: number[]): Mapping[] {
307307
if (rawMap === null) {
308308
return [];
309309
}
@@ -330,11 +330,13 @@ export function parseMappings(
330330
const generatedSegment: SegmentMarker = {
331331
line: generatedLine,
332332
column: generatedColumn,
333+
position: generatedSourceStartOfLinePositions[generatedLine] + generatedColumn,
333334
next: undefined,
334335
};
335336
const originalSegment: SegmentMarker = {
336337
line,
337338
column,
339+
position: originalSource.startOfLinePositions[line] + column,
338340
next: undefined,
339341
};
340342
mappings.push({name, generatedSegment, originalSegment, originalSource});

packages/compiler-cli/ngcc/test/sourcemaps/segment_marker_spec.ts

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,65 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {compareSegments, offsetSegment, segmentDiff} from '../../src/sourcemaps/segment_marker';
8+
import {compareSegments, offsetSegment} from '../../src/sourcemaps/segment_marker';
99
import {computeStartOfLinePositions} from '../../src/sourcemaps/source_file';
1010

1111
describe('SegmentMarker utils', () => {
1212
describe('compareSegments()', () => {
1313
it('should return 0 if the segments are the same', () => {
1414
expect(compareSegments(
15-
{line: 0, column: 0, next: undefined}, {line: 0, column: 0, next: undefined}))
15+
{line: 0, column: 0, position: 0, next: undefined},
16+
{line: 0, column: 0, position: 0, next: undefined}))
1617
.toEqual(0);
1718
expect(compareSegments(
18-
{line: 123, column: 0, next: undefined}, {line: 123, column: 0, next: undefined}))
19+
{line: 123, column: 0, position: 200, next: undefined},
20+
{line: 123, column: 0, position: 200, next: undefined}))
1921
.toEqual(0);
2022
expect(compareSegments(
21-
{line: 0, column: 45, next: undefined}, {line: 0, column: 45, next: undefined}))
23+
{line: 0, column: 45, position: 45, next: undefined},
24+
{line: 0, column: 45, position: 45, next: undefined}))
2225
.toEqual(0);
23-
expect(
24-
compareSegments(
25-
{line: 123, column: 45, next: undefined}, {line: 123, column: 45, next: undefined}))
26+
expect(compareSegments(
27+
{line: 123, column: 45, position: 245, next: undefined},
28+
{line: 123, column: 45, position: 245, next: undefined}))
2629
.toEqual(0);
2730
});
2831

2932
it('should return a negative number if the first segment is before the second segment', () => {
3033
expect(compareSegments(
31-
{line: 0, column: 0, next: undefined}, {line: 0, column: 45, next: undefined}))
34+
{line: 0, column: 0, position: 0, next: undefined},
35+
{line: 0, column: 45, position: 45, next: undefined}))
3236
.toBeLessThan(0);
3337
expect(compareSegments(
34-
{line: 123, column: 0, next: undefined}, {line: 123, column: 45, next: undefined}))
38+
{line: 123, column: 0, position: 200, next: undefined},
39+
{line: 123, column: 45, position: 245, next: undefined}))
3540
.toBeLessThan(0);
3641
expect(compareSegments(
37-
{line: 13, column: 45, next: undefined}, {line: 123, column: 45, next: undefined}))
42+
{line: 13, column: 45, position: 75, next: undefined},
43+
{line: 123, column: 45, position: 245, next: undefined}))
3844
.toBeLessThan(0);
3945
expect(compareSegments(
40-
{line: 13, column: 45, next: undefined}, {line: 123, column: 9, next: undefined}))
46+
{line: 13, column: 45, position: 75, next: undefined},
47+
{line: 123, column: 9, position: 209, next: undefined}))
4148
.toBeLessThan(0);
4249
});
4350

4451
it('should return a positive number if the first segment is after the second segment', () => {
4552
expect(compareSegments(
46-
{line: 0, column: 45, next: undefined}, {line: 0, column: 0, next: undefined}))
53+
{line: 0, column: 45, position: 45, next: undefined},
54+
{line: 0, column: 0, position: 0, next: undefined}))
4755
.toBeGreaterThan(0);
4856
expect(compareSegments(
49-
{line: 123, column: 45, next: undefined}, {line: 123, column: 0, next: undefined}))
57+
{line: 123, column: 45, position: 245, next: undefined},
58+
{line: 123, column: 0, position: 200, next: undefined}))
5059
.toBeGreaterThan(0);
5160
expect(compareSegments(
52-
{line: 123, column: 45, next: undefined}, {line: 13, column: 45, next: undefined}))
61+
{line: 123, column: 45, position: 245, next: undefined},
62+
{line: 13, column: 45, position: 75, next: undefined}))
5363
.toBeGreaterThan(0);
5464
expect(compareSegments(
55-
{line: 123, column: 9, next: undefined}, {line: 13, column: 45, next: undefined}))
65+
{line: 123, column: 9, position: 209, next: undefined},
66+
{line: 13, column: 45, position: 75, next: undefined}))
5667
.toBeGreaterThan(0);
5768
});
5869
});
@@ -61,38 +72,38 @@ describe('SegmentMarker utils', () => {
6172
it('should return an identical marker if offset is 0', () => {
6273
const startOfLinePositions =
6374
computeStartOfLinePositions('012345\n0123456789\r\n012*4567\n0123456');
64-
const marker = {line: 2, column: 3, next: undefined};
75+
const marker = {line: 2, column: 3, position: 20, next: undefined};
6576
expect(offsetSegment(startOfLinePositions, marker, 0)).toBe(marker);
6677
});
6778

6879
it('should return a new marker offset by the given chars', () => {
6980
const startOfLinePositions =
7081
computeStartOfLinePositions('012345\n0123456789\r\n012*4567\n0123456');
71-
const marker = {line: 2, column: 3, next: undefined};
82+
const marker = {line: 2, column: 3, position: 21, next: undefined};
7283
expect(offsetSegment(startOfLinePositions, marker, 1))
73-
.toEqual({line: 2, column: 4, next: undefined});
84+
.toEqual({line: 2, column: 4, position: 22, next: undefined});
7485
expect(offsetSegment(startOfLinePositions, marker, 2))
75-
.toEqual({line: 2, column: 5, next: undefined});
86+
.toEqual({line: 2, column: 5, position: 23, next: undefined});
7687
expect(offsetSegment(startOfLinePositions, marker, 4))
77-
.toEqual({line: 2, column: 7, next: undefined});
88+
.toEqual({line: 2, column: 7, position: 25, next: undefined});
7889
expect(offsetSegment(startOfLinePositions, marker, 6))
79-
.toEqual({line: 3, column: 0, next: undefined});
90+
.toEqual({line: 3, column: 0, position: 27, next: undefined});
8091
expect(offsetSegment(startOfLinePositions, marker, 8))
81-
.toEqual({line: 3, column: 2, next: undefined});
92+
.toEqual({line: 3, column: 2, position: 29, next: undefined});
8293
expect(offsetSegment(startOfLinePositions, marker, 20))
83-
.toEqual({line: 3, column: 14, next: undefined});
94+
.toEqual({line: 3, column: 14, position: 41, next: undefined});
8495
expect(offsetSegment(startOfLinePositions, marker, -1))
85-
.toEqual({line: 2, column: 2, next: undefined});
96+
.toEqual({line: 2, column: 2, position: 20, next: undefined});
8697
expect(offsetSegment(startOfLinePositions, marker, -2))
87-
.toEqual({line: 2, column: 1, next: undefined});
98+
.toEqual({line: 2, column: 1, position: 19, next: undefined});
8899
expect(offsetSegment(startOfLinePositions, marker, -3))
89-
.toEqual({line: 2, column: 0, next: undefined});
100+
.toEqual({line: 2, column: 0, position: 18, next: undefined});
90101
expect(offsetSegment(startOfLinePositions, marker, -4))
91-
.toEqual({line: 1, column: 10, next: undefined});
102+
.toEqual({line: 1, column: 10, position: 17, next: undefined});
92103
expect(offsetSegment(startOfLinePositions, marker, -6))
93-
.toEqual({line: 1, column: 8, next: undefined});
104+
.toEqual({line: 1, column: 8, position: 15, next: undefined});
94105
expect(offsetSegment(startOfLinePositions, marker, -16))
95-
.toEqual({line: 0, column: 5, next: undefined});
106+
.toEqual({line: 0, column: 5, position: 5, next: undefined});
96107
});
97108
});
98109
});

0 commit comments

Comments
 (0)