Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some buffer handling optimizations #4115

Merged
merged 14 commits into from
Dec 7, 2022
38 changes: 26 additions & 12 deletions src/common/buffer/BufferLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const w: { startIndex: number } = {
startIndex: 0
};

const EMPTY_DATA = new Uint32Array(0);

/**
* Typed array based bufferline implementation.
*
Expand All @@ -64,7 +66,7 @@ export class BufferLine implements IBufferLine {
public length: number;

constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) {
this._data = new Uint32Array(cols * CELL_SIZE);
this._data = cols ? new Uint32Array(cols * CELL_SIZE) : EMPTY_DATA;
const cell = fillCellData || CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
for (let i = 0; i < cols; ++i) {
this.setCell(i, cell);
Expand Down Expand Up @@ -339,35 +341,47 @@ export class BufferLine implements IBufferLine {
if (cols === this.length) {
return;
}
const fourByteCells = cols * CELL_SIZE;
if (cols > this.length) {
const data = new Uint32Array(cols * CELL_SIZE);
if (this.length) {
if (cols * CELL_SIZE < this._data.length) {
data.set(this._data.subarray(0, cols * CELL_SIZE));
} else {
if (this._data.buffer.byteLength >= fourByteCells * 4) {
// optimization: avoid alloc and data copy if buffer has enough room
this._data = new Uint32Array(this._data.buffer, 0, fourByteCells);
} else {
// slow path: new alloc and full data copy
const data = new Uint32Array(fourByteCells);
if (this.length && this._data.length <= fourByteCells) {
data.set(this._data);
}
this._data = data;
}
this._data = data;
for (let i = this.length; i < cols; ++i) {
this.setCell(i, fillCellData);
}
} else {
if (cols) {
const data = new Uint32Array(cols * CELL_SIZE);
data.set(this._data.subarray(0, cols * CELL_SIZE));
this._data = data;
// Remove any cut off combined data, FIXME: repeat this for extended attrs
// optimization: just shrink the view on existing buffer
// FIXME: register requestIdleCallback() to cleanup memory, if buffer >2x used view
this._data = this._data.subarray(0, fourByteCells);
// Remove any cut off combined data
const keys = Object.keys(this._combined);
for (let i = 0; i < keys.length; i++) {
const key = parseInt(keys[i], 10);
if (key >= cols) {
delete this._combined[key];
}
}
// remove any cut off extended attributes
const extKeys = Object.keys(this._extendedAttrs);
for (let i = 0; i < extKeys.length; i++) {
const key = parseInt(extKeys[i], 10);
if (key >= cols) {
delete this._extendedAttrs[key];
}
}
} else {
this._data = new Uint32Array(0);
this._data = EMPTY_DATA;
this._combined = {};
this._extendedAttrs = {};
}
}
this.length = cols;
Expand Down