mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
minor fixes:
- better perf for short DCS without params (8 times faster) - test perf for class and string based interfaces of OSC and DCS separately - undo wrong commit on parser
This commit is contained in:
@@ -100,19 +100,27 @@ export class DcsParser implements IDcsParser {
|
||||
}
|
||||
}
|
||||
|
||||
// predefine empty params as [0] (ZDM)
|
||||
const EMPTY_PARAMS = new Params();
|
||||
EMPTY_PARAMS.addParam(0);
|
||||
|
||||
/**
|
||||
* Convenient class to create a DCS handler from a single callback function.
|
||||
* Note: The payload is currently limited to 50 MB (hardcoded).
|
||||
*/
|
||||
export class DcsHandler implements IDcsHandler {
|
||||
private _data = '';
|
||||
private _params: IParams | undefined;
|
||||
private _params: IParams = EMPTY_PARAMS;
|
||||
private _hitLimit: boolean = false;
|
||||
|
||||
constructor(private _handler: (data: string, params: IParams) => boolean) {}
|
||||
|
||||
public hook(params: IParams): void {
|
||||
this._params = params.clone();
|
||||
// since we need to preserve params until `unhook`, we have to clone it
|
||||
// (only borrowed from parser and spans multiple parser states)
|
||||
// perf optimization:
|
||||
// clone only, if we have non empty params, otherwise stick with default
|
||||
this._params = (params.length > 1 || params.params[0]) ? params.clone() : EMPTY_PARAMS;
|
||||
this._data = '';
|
||||
this._hitLimit = false;
|
||||
}
|
||||
@@ -133,9 +141,9 @@ export class DcsHandler implements IDcsHandler {
|
||||
if (this._hitLimit) {
|
||||
ret = false;
|
||||
} else if (success) {
|
||||
ret = this._handler(this._data, this._params || new Params());
|
||||
ret = this._handler(this._data, this._params);
|
||||
}
|
||||
this._params = undefined;
|
||||
this._params = EMPTY_PARAMS;
|
||||
this._data = '';
|
||||
this._hitLimit = false;
|
||||
return ret;
|
||||
|
||||
@@ -582,21 +582,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
if (++j >= length || (code = data[j]) === 0x18 || code === 0x1a || code === 0x1b || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
|
||||
dcs.put(data, i, j);
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
if (++j >= length || (code = data[j]) === 0x18 || code === 0x1a || code === 0x1b || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
|
||||
dcs.put(data, i, j);
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
if (++j >= length || (code = data[j]) === 0x18 || code === 0x1a || code === 0x1b || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
|
||||
dcs.put(data, i, j);
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParserAction.DCS_UNHOOK:
|
||||
@@ -613,7 +598,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
case ParserAction.OSC_PUT:
|
||||
// inner loop: 0x20 (SP) included, 0x7F (DEL) included
|
||||
for (let j = i + 1; ; j++) {
|
||||
if (j >= length || (code = data[j]) < 0x20 || (code > 0x7f && code <= 0x9f)) {
|
||||
if (j >= length || (code = data[j]) < 0x20 || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
|
||||
osc.put(data, i, j);
|
||||
i = j - 1;
|
||||
break;
|
||||
|
||||
@@ -6,9 +6,11 @@ import { perfContext, before, beforeEach, ThroughputRuntimeCase } from 'xterm-be
|
||||
|
||||
import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser';
|
||||
import { C0, C1 } from 'common/data/EscapeSequences';
|
||||
import { IDcsHandler, IParams } from 'common/parser/Types';
|
||||
import { IDcsHandler, IOscHandler, IParams } from 'common/parser/Types';
|
||||
import { OscHandler } from 'common/parser/OscParser';
|
||||
import { DcsHandler } from '../../out/common/parser/DcsParser';
|
||||
|
||||
const SIZE = 5000000;
|
||||
|
||||
function toUtf32(s: string): Uint32Array {
|
||||
const result = new Uint32Array(s.length);
|
||||
@@ -18,10 +20,16 @@ function toUtf32(s: string): Uint32Array {
|
||||
return result;
|
||||
}
|
||||
|
||||
class DcsHandler implements IDcsHandler {
|
||||
class FastDcsHandler implements IDcsHandler {
|
||||
public hook(params: IParams): void {}
|
||||
public put(data: Uint32Array, start: number, end: number): void {}
|
||||
public unhook(): boolean { return true; }
|
||||
public unhook(success: boolean): boolean { return true; }
|
||||
}
|
||||
|
||||
class FastOscHandler implements IOscHandler {
|
||||
public start(): void {}
|
||||
public put(data: Uint32Array, start: number, end: number): void {}
|
||||
public end(success: boolean): boolean { return true; }
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +89,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
parser.setExecuteHandler(C1.NEL, () => true);
|
||||
parser.setExecuteHandler(C1.HTS, () => true);
|
||||
parser.registerOscHandler(0, new OscHandler(data => true));
|
||||
parser.registerOscHandler(2, new OscHandler(data => true));
|
||||
parser.registerOscHandler(1, new FastOscHandler());
|
||||
parser.registerEscHandler({final: '7'}, () => true);
|
||||
parser.registerEscHandler({final: '8'}, () => true);
|
||||
parser.registerEscHandler({final: 'D'}, () => true);
|
||||
@@ -98,14 +106,15 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
parser.registerEscHandler({final: '~'}, () => true);
|
||||
parser.registerEscHandler({intermediates: '%', final: '@'}, () => true);
|
||||
parser.registerEscHandler({intermediates: '%', final: 'G'}, () => true);
|
||||
parser.registerDcsHandler({final: 'q'}, new DcsHandler());
|
||||
parser.registerDcsHandler({final: 'p'}, new DcsHandler(data => true));
|
||||
parser.registerDcsHandler({final: 'q'}, new FastDcsHandler());
|
||||
});
|
||||
|
||||
perfContext('PRINT - a', () => {
|
||||
before(() => {
|
||||
const data = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -120,7 +129,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
before(() => {
|
||||
const data = '\n\n\n\n\n\n\n';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -135,7 +144,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
before(() => {
|
||||
const data = '\x1bE\x1bE\x1bE\x1bE\x1bE\x1bE\x1bE\x1bE\x1bE\x1bE';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -150,7 +159,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
before(() => {
|
||||
const data = '\x1b%G\x1b%G\x1b%G\x1b%G\x1b%G\x1b%G\x1b%G\x1b%G\x1b%G\x1b%G';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -165,7 +174,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
before(() => {
|
||||
const data = '\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -180,7 +189,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
before(() => {
|
||||
const data = '\x1b[?p\x1b[?p\x1b[?p\x1b[?p\x1b[?p\x1b[?p\x1b[?p\x1b[?p\x1b[?p\x1b[?p';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -195,7 +204,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
before(() => {
|
||||
const data = '\x1b[1;2m\x1b[1;2m\x1b[1;2m\x1b[1;2m\x1b[1;2m\x1b[1;2m\x1b[1;2m\x1b[1;2m\x1b[1;2m\x1b[1;2m';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -210,7 +219,7 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
before(() => {
|
||||
const data = '\x1b[1;2;3;4;5;6;7;8;9;0m\x1b[1;2;3;4;5;6;7;8;9;0m\x1b[1;2;3;4;5;6;7;8;9;0m';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -221,11 +230,11 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('OSC (short) - OSC 0;hi ST', () => {
|
||||
perfContext('OSC string interface (short seq) - OSC 0;hi ST', () => {
|
||||
before(() => {
|
||||
const data = '\x1b]0;hi\x1b\\\x1b]0;hi\x1b\\\x1b]0;hi\x1b\\\x1b]0;hi\x1b\\x1b]0;hi\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -236,11 +245,11 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('OSC (long) - OSC 0;<text> ST', () => {
|
||||
perfContext('OSC string interface (long seq) - OSC 0;<text> ST', () => {
|
||||
before(() => {
|
||||
const data = '\x1b]0;Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -251,11 +260,41 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('DCS (short)', () => {
|
||||
perfContext('OSC class interface (short seq) - OSC 0;hi ST', () => {
|
||||
before(() => {
|
||||
const data = '\x1bPq~~\x1b\\';
|
||||
const data = '\x1b]1;hi\x1b\\\x1b]1;hi\x1b\\\x1b]1;hi\x1b\\\x1b]1;hi\x1b\\x1b]1;hi\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
});
|
||||
new ThroughputRuntimeCase('', () => {
|
||||
parser.parse(parsed, parsed.length);
|
||||
return {payloadSize: parsed.length};
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('OSC class interface (long seq) - OSC 0;<text> ST', () => {
|
||||
before(() => {
|
||||
const data = '\x1b]1;Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
});
|
||||
new ThroughputRuntimeCase('', () => {
|
||||
parser.parse(parsed, parsed.length);
|
||||
return {payloadSize: parsed.length};
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('DCS string interface (short seq)', () => {
|
||||
before(() => {
|
||||
const data = '\x1bPphi\x1b\\\x1bPphi\x1b\\\x1bPphi\x1b\\\x1bPphi\x1b\\\x1bPphi\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
@@ -266,11 +305,41 @@ perfContext('Parser throughput - 50MB data', () => {
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('DCS (long)', () => {
|
||||
perfContext('DCS string interface (long seq)', () => {
|
||||
before(() => {
|
||||
const data = '\x1bPq#0;2;0;0;0#1;2;100;100;0#2;2;0;100;0#1~~@@vv@@~~@@~~$#2??}}GG}}??}}??-#1!14@\x1b\\';
|
||||
const data = '\x1bPpLorem ipsum dolor sit amet, consetetur sadipscing elitr.\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < 50000000) {
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
});
|
||||
new ThroughputRuntimeCase('', async () => {
|
||||
parser.parse(parsed, parsed.length);
|
||||
return {payloadSize: parsed.length};
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('DCS class interface (short seq)', () => {
|
||||
before(() => {
|
||||
const data = '\x1bPqhi\x1b\\\x1bPqhi\x1b\\\x1bPqhi\x1b\\\x1bPqhi\x1b\\\x1bPqhi\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
});
|
||||
new ThroughputRuntimeCase('', async () => {
|
||||
parser.parse(parsed, parsed.length);
|
||||
return {payloadSize: parsed.length};
|
||||
}, {fork: true}).showAverageThroughput();
|
||||
});
|
||||
|
||||
perfContext('DCS class interface (long seq)', () => {
|
||||
before(() => {
|
||||
const data = '\x1bPqLorem ipsum dolor sit amet, consetetur sadipscing elitr.\x1b\\';
|
||||
let content = '';
|
||||
while (content.length < SIZE) {
|
||||
content += data;
|
||||
}
|
||||
parsed = toUtf32(content);
|
||||
|
||||
Reference in New Issue
Block a user