lazy cleanup on buffer

This commit is contained in:
Jörg Breitbart
2022-09-28 15:57:58 +02:00
parent e58f73dc82
commit 785b932d75
3 changed files with 32 additions and 6 deletions
+1
View File
@@ -206,6 +206,7 @@ export interface IBufferLine {
deleteCells(pos: number, n: number, fill: ICellData, eraseAttr?: IAttributeData): void;
replaceCells(start: number, end: number, fill: ICellData, eraseAttr?: IAttributeData, respectProtect?: boolean): void;
resize(cols: number, fill: ICellData): boolean;
cleanupMemory(): number;
fill(fillCellData: ICellData, respectProtect?: boolean): void;
copyFrom(line: IBufferLine): void;
clone(): IBufferLine;
+27 -2
View File
@@ -14,6 +14,7 @@ import { Marker } from 'common/buffer/Marker';
import { IOptionsService, IBufferService } from 'common/services/Services';
import { DEFAULT_CHARSET } from 'common/data/Charsets';
import { ExtendedAttrs } from 'common/buffer/AttributeData';
import { DebouncedIdleTask } from 'common/TaskQueue';
export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1
@@ -151,6 +152,9 @@ export class Buffer implements IBuffer {
// store reference to null cell with default attrs
const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);
// defer memory cleanup of bufferlines
let needsCleanup = 0;
// Increase max length if needed before adjustments to allow space to fill
// as required.
const newMaxLength = this._getCorrectBufferLength(newRows);
@@ -164,7 +168,7 @@ export class Buffer implements IBuffer {
// Deal with columns increasing (reducing needs to happen after reflow)
if (this._cols < newCols) {
for (let i = 0; i < this.lines.length; i++) {
this.lines.get(i)!.resize(newCols, nullCell);
needsCleanup |= +this.lines.get(i)!.resize(newCols, nullCell);
}
}
@@ -243,13 +247,34 @@ export class Buffer implements IBuffer {
// Trim the end of the line off if cols shrunk
if (this._cols > newCols) {
for (let i = 0; i < this.lines.length; i++) {
this.lines.get(i)!.resize(newCols, nullCell);
needsCleanup |= +this.lines.get(i)!.resize(newCols, nullCell);
}
}
}
this._cols = newCols;
this._rows = newRows;
if (needsCleanup) {
this._memoryCleanupTask.set(() => this._cleanupMemory());
} else {
// FIXME: DebouncedIdleTask has no clear method?
this._memoryCleanupTask.set(() => {});
}
}
private _memoryCleanupTask: DebouncedIdleTask = new DebouncedIdleTask();
private _cleanupMemory(): void {
let counted = 0;
for (let i = 0; i < this.lines.length; i++) {
counted += this.lines.get(i)!.cleanupMemory();
// throttle to 5k lines
if (counted > 5000) {
this._memoryCleanupTask.set(() => this._cleanupMemory());
break;
}
}
}
private get _isReflowEnabled(): boolean {
+4 -4
View File
@@ -347,7 +347,7 @@ export class BufferLine implements IBufferLine {
*/
public resize(cols: number, fillCellData: ICellData): boolean {
if (cols === this.length) {
return this._data.length * 4 < this._data.buffer.byteLength * CLEANUP_THRESHOLD;
return this._data.length * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength;
}
const uint32Cells = cols * CELL_SIZE;
if (cols > this.length) {
@@ -384,7 +384,7 @@ export class BufferLine implements IBufferLine {
}
}
this.length = cols;
return uint32Cells * 4 < this._data.buffer.byteLength * CLEANUP_THRESHOLD;
return uint32Cells * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength;
}
/**
@@ -393,8 +393,8 @@ export class BufferLine implements IBufferLine {
* memory by a factor of CLEANUP_THRESHOLD.
* Returns 0 or 1 indicating whether a cleanup happened.
*/
public cleanupBuffer(): number {
if (this._data.length * 4 < this._data.buffer.byteLength * CLEANUP_THRESHOLD) {
public cleanupMemory(): number {
if (this._data.length * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength) {
const data = new Uint32Array(this._data.length);
data.set(this._data);
this._data = data;