Skip to content

Commit ceb955b

Browse files
committed
Merge branch 'reuse_bufferlines' of git+ssh://github.com/jerch/xterm.js into reuse_bufferlines
2 parents 33a3580 + 43e9911 commit ceb955b

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

src/Buffer.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,13 @@ export class Buffer implements IBuffer {
5555
}
5656

5757
public setBufferLineFactory(type: string): void {
58+
this.lines.recycling = false;
59+
this.lines.recycleHeap = [];
5860
if (type === 'TypedArray') {
5961
if (this._bufferLineConstructor !== BufferLineTypedArray) {
6062
this._bufferLineConstructor = BufferLineTypedArray;
6163
this._recreateLines();
64+
this.lines.recycling = true;
6265
}
6366
} else {
6467
if (this._bufferLineConstructor !== BufferLine) {
@@ -81,8 +84,26 @@ export class Buffer implements IBuffer {
8184
}
8285

8386
public getBlankLine(attr: number, isWrapped?: boolean): IBufferLine {
84-
const fillCharData: CharData = [attr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];
85-
return new this._bufferLineConstructor(this._terminal.cols, fillCharData, isWrapped);
87+
// JS array without recycling
88+
if (this._bufferLineConstructor === BufferLine) {
89+
const fillCharData: CharData = [attr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];
90+
return new this._bufferLineConstructor(this._terminal.cols, fillCharData, isWrapped);
91+
}
92+
93+
// typed array with recycling
94+
let blank: IBufferLine = (this as any)._blank;
95+
if (!blank || blank.length !== this._terminal.cols) {
96+
const fillCharData: CharData = [attr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE];
97+
blank = new this._bufferLineConstructor(this._terminal.cols, fillCharData, isWrapped);
98+
(this as any)._blank = blank;
99+
}
100+
blank.isWrapped = !!(isWrapped);
101+
const recycled = this.lines.recycleHeap.pop();
102+
if (recycled) {
103+
recycled.copyFrom(blank);
104+
return recycled;
105+
}
106+
return blank.clone();
86107
}
87108

88109
public get hasScrollback(): boolean {
@@ -126,7 +147,7 @@ export class Buffer implements IBuffer {
126147
* Clears the buffer to it's initial state, discarding all previous data.
127148
*/
128149
public clear(): void {
129-
this.setBufferLineFactory(this._terminal.options.experimentalBufferLineImpl);
150+
// this.setBufferLineFactory(this._terminal.options.experimentalBufferLineImpl);
130151
this.ydisp = 0;
131152
this.ybase = 0;
132153
this.y = 0;
@@ -135,6 +156,7 @@ export class Buffer implements IBuffer {
135156
this.scrollTop = 0;
136157
this.scrollBottom = this._terminal.rows - 1;
137158
this.setupTabStops();
159+
this.setBufferLineFactory(this._terminal.options.experimentalBufferLineImpl);
138160
}
139161

140162
/**

src/common/CircularList.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export class CircularList<T> extends EventEmitter implements ICircularList<T> {
1414
protected _array: (T | undefined)[];
1515
private _startIndex: number;
1616
private _length: number;
17+
public recycleHeap: T[];
18+
public recycling: boolean = false;
1719

1820
constructor(
1921
private _maxLength: number
@@ -22,6 +24,7 @@ export class CircularList<T> extends EventEmitter implements ICircularList<T> {
2224
this._array = new Array<T>(this._maxLength);
2325
this._startIndex = 0;
2426
this._length = 0;
27+
this.recycleHeap = [];
2528
}
2629

2730
public get maxLength(): number {
@@ -79,6 +82,13 @@ export class CircularList<T> extends EventEmitter implements ICircularList<T> {
7982
* @param value The value to set.
8083
*/
8184
public set(index: number, value: T | undefined): void {
85+
if (this.recycling) {
86+
const line = this._array[this._getCyclicIndex(this._length)];
87+
if (line) {
88+
this.recycleHeap.push(line);
89+
}
90+
}
91+
8292
this._array[this._getCyclicIndex(index)] = value;
8393
}
8494

@@ -88,6 +98,13 @@ export class CircularList<T> extends EventEmitter implements ICircularList<T> {
8898
* @param value The value to push onto the list.
8999
*/
90100
public push(value: T): void {
101+
if (this.recycling) {
102+
const line = this._array[this._getCyclicIndex(this._length)];
103+
if (line) {
104+
this.recycleHeap.push(line);
105+
}
106+
}
107+
91108
this._array[this._getCyclicIndex(this._length)] = value;
92109
if (this._length === this._maxLength) {
93110
this._startIndex++;
@@ -139,6 +156,13 @@ export class CircularList<T> extends EventEmitter implements ICircularList<T> {
139156
// Delete items
140157
if (deleteCount) {
141158
for (let i = start; i < this._length - deleteCount; i++) {
159+
if (this.recycling) {
160+
const line = this._array[this._getCyclicIndex(this._length)];
161+
if (line) {
162+
this.recycleHeap.push(line);
163+
}
164+
}
165+
142166
this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)];
143167
}
144168
this._length -= deleteCount;

src/common/Types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export interface IKeyboardEvent {
2424
export interface ICircularList<T> extends IEventEmitter {
2525
length: number;
2626
maxLength: number;
27+
recycleHeap: T[];
28+
recycling: boolean;
2729

2830
get(index: number): T | undefined;
2931
set(index: number, value: T): void;

0 commit comments

Comments
 (0)