Skip to content

Commit 65880d8

Browse files
authored
improv: shlex.split() function heap allocs & perf for large compile commands (#4458)
* direct improve shlex heap allocs & perf for large compile commands * Fix lint issues & update CHANGELOG
1 parent 024d14d commit 65880d8

File tree

2 files changed

+18
-18
lines changed

2 files changed

+18
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Improvements:
1313

1414
- Add name de-mangling for C++ symbols in the Test Explorer view when running tests with coverage. [#4340](https://github.com/microsoft/vscode-cmake-tools/pull/4340) [@rjaegers](https://github.com/rjaegers)
1515
- No longer convert paths on lowercase on MacOS to enable cpp tools to resolve them. [#4325](https://github.com/microsoft/vscode-cmake-tools/pull/4325) [@tringenbach](https://github.com/tringenbach)
16+
- Speedup & reduce heap allocations in shlex split module function. Significant gains for mid-large compile_commands.json - CompilationDatabase construction. [#4458](https://github.com/microsoft/vscode-cmake-tools/pull/4458) [@borjamunozf](https://github.com/borjamunozf)
1617

1718
Bug Fixes:
1819

src/shlex.ts

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,67 +13,66 @@ export function* split(str: string, opt?: ShlexOptions): Iterable<string> {
1313
opt = opt || {
1414
mode: process.platform === 'win32' ? 'windows' : 'posix'
1515
};
16+
1617
const quoteChars = opt.mode === 'posix' ? '\'"' : '"';
1718
const escapeChars = '\\';
1819
let escapeChar: string | undefined;
19-
let token: string | undefined;
20+
let token: string[] = [];
2021
let isSubQuote: boolean = false;
2122

2223
for (let i = 0; i < str.length; ++i) {
2324
const char = str.charAt(i);
25+
2426
if (escapeChar) {
2527
if (char === '\n') {
2628
// Do nothing
2729
} else if (escapeChars.includes(char)) {
28-
token = (token || '') + char;
30+
token.push(char);
2931
} else {
30-
token = (token || '') + escapeChar + char;
32+
token.push(escapeChar, char); // Append escape sequence
3133
}
3234
// We parsed an escape seq. Reset to no escape
3335
escapeChar = undefined;
3436
continue;
3537
}
3638

3739
if (escapeChars.includes(char)) {
38-
// We're parsing an escape sequence.
40+
// Start escape sequence
3941
escapeChar = char;
4042
continue;
4143
}
4244

4345
if (isSubQuote) {
4446
if (quoteChars.includes(char)) {
45-
// Reached the end of a sub-quoted token.
47+
// End of sub-quoted token
4648
isSubQuote = false;
47-
token = (token || '') + char;
49+
token.push(char);
4850
continue;
4951
}
50-
// Another quoted char
51-
token = (token || '') + char;
52+
token.push(char);
5253
continue;
5354
}
5455

5556
if (quoteChars.includes(char)) {
56-
// Beginning of a sub-quoted token
57+
// Beginning of a subquoted token
5758
isSubQuote = true;
58-
// Accumulate
59-
token = (token || '') + char;
59+
token.push(char);
6060
continue;
6161
}
6262

6363
if (!isSubQuote && /[\t \n\r\f]/.test(char)) {
64-
if (token !== undefined) {
65-
yield token;
64+
if (token.length > 0) {
65+
yield token.join('');
6666
}
67-
token = undefined;
67+
token = [];
6868
continue;
6969
}
7070

71-
// Accumulate
72-
token = (token || '') + char;
71+
token.push(char);
7372
}
7473

75-
if (token !== undefined) {
76-
yield token;
74+
if (token.length > 0) {
75+
yield token.join('');
7776
}
7877
}
7978

0 commit comments

Comments
 (0)