diff --git a/src/vs/base/common/buffer.ts b/src/vs/base/common/buffer.ts index cf34296e74c287e41f12ccefeab996931694aabd..7b4e9cc8d66864d28cb8f5a2513a2124f52098d2 100644 --- a/src/vs/base/common/buffer.ts +++ b/src/vs/base/common/buffer.ts @@ -78,7 +78,10 @@ export class VSBuffer { } slice(start?: number, end?: number): VSBuffer { - return new VSBuffer(this.buffer.slice(start, end)); + // IMPORTANT: use subarray instead of slice because TypedArray#slice + // creates shallow copy and NodeBuffer#slice doesn't. The use of subarray + // ensures the same, performant, behaviour. + return new VSBuffer(this.buffer.subarray(start!/*bad lib.d.ts*/, end)); } set(array: VSBuffer, offset?: number): void { @@ -437,4 +440,4 @@ class VSBufferWriteableStreamImpl implements VSBufferWriteableStream { this.listeners.end.length = 0; } } -} \ No newline at end of file +} diff --git a/src/vs/base/test/common/buffer.test.ts b/src/vs/base/test/node/buffer.test.ts similarity index 90% rename from src/vs/base/test/common/buffer.test.ts rename to src/vs/base/test/node/buffer.test.ts index c5a3cd676eefae006fe0ad2ac9b2e9bda2fc4dcf..65f84a66ddf72e713eafc3e961de859f2ad35310 100644 --- a/src/vs/base/test/common/buffer.test.ts +++ b/src/vs/base/test/node/buffer.test.ts @@ -364,4 +364,42 @@ suite('Buffer', () => { assert.equal(ended, false); assert.equal(errors.length, 0); }); + + test('Performance issue with VSBuffer#slice #76076', function () { + // Buffer#slice creates a view + { + const buff = Buffer.from([10, 20, 30, 40]); + const b2 = buff.slice(1, 3); + assert.equal(buff[1], 20); + assert.equal(b2[0], 20); + + buff[1] = 17; // modify buff AND b2 + assert.equal(buff[1], 17); + assert.equal(b2[0], 17); + } + + // TypedArray#slice creates a copy + { + const unit = new Uint8Array([10, 20, 30, 40]); + const u2 = unit.slice(1, 3); + assert.equal(unit[1], 20); + assert.equal(u2[0], 20); + + unit[1] = 17; // modify unit, NOT b2 + assert.equal(unit[1], 17); + assert.equal(u2[0], 20); + } + + // TypedArray#subarray creates a view + { + const unit = new Uint8Array([10, 20, 30, 40]); + const u2 = unit.subarray(1, 3); + assert.equal(unit[1], 20); + assert.equal(u2[0], 20); + + unit[1] = 17; // modify unit AND b2 + assert.equal(unit[1], 17); + assert.equal(u2[0], 17); + } + }); });