1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.Test = void 0;
|
4 | const Fork_1 = require("./Fork");
|
5 | const Messager_1 = require("./Messager");
|
6 | const getDiff_1 = require("./getDiff");
|
7 | class ForkContext {
|
8 | _test;
|
9 | _processors;
|
10 | _resolve;
|
11 | _benchName;
|
12 | _options;
|
13 | _ended = false;
|
14 | constructor(_test, _processors, _resolve, _benchName, _options) {
|
15 | this._test = _test;
|
16 | this._processors = _processors;
|
17 | this._resolve = _resolve;
|
18 | this._benchName = _benchName;
|
19 | this._options = _options;
|
20 | }
|
21 | start() {
|
22 | const setup = {
|
23 | testIndex: this._test.index,
|
24 | benchName: this._benchName,
|
25 | samples: Math.min(Math.ceil(this._options.samples * 0.1), this._options.samples - this._test.samples.length),
|
26 | time: this._options.time
|
27 | };
|
28 | const worker = Fork_1.Fork.fork({
|
29 | ["ISO_BENCH_SETUP"]: JSON.stringify(setup)
|
30 | });
|
31 | this._listenForCompletionMessage(worker.stdio[3]);
|
32 | this._listenForProcessExit(worker);
|
33 | }
|
34 | _processMessage(msg) {
|
35 | if (!this._ended) {
|
36 | if (msg.error != null) {
|
37 | this._test.opMs = 0;
|
38 | this._test.error = msg.error;
|
39 | this._ended = true;
|
40 | this._resolve();
|
41 | }
|
42 | else if (msg.done) {
|
43 | this._ended = true;
|
44 | if (this._test.samples.length >= this._options.samples) {
|
45 | this._resolve();
|
46 | }
|
47 | else {
|
48 | new ForkContext(this._test, this._processors, this._resolve, this._benchName, this._options).start();
|
49 | }
|
50 | }
|
51 | else {
|
52 | const sample = {
|
53 | cycles: msg.cycles,
|
54 | time: msg.diff,
|
55 | ops: msg.cycles / msg.diff
|
56 | };
|
57 | this._test.samples.push(sample);
|
58 | this._test.totalTime += msg.diff;
|
59 | this._test.opMs = this._test.samples.reduce((total, sample) => total + sample.ops, 0) / this._test.samples.length;
|
60 | for (const processor of this._processors) {
|
61 | processor.sample && processor.sample(this._test, sample);
|
62 | }
|
63 | }
|
64 | }
|
65 | }
|
66 | _listenForCompletionMessage(stream) {
|
67 | let size = null;
|
68 | stream.on("readable", () => {
|
69 | try {
|
70 | while (stream.readable) {
|
71 | if (this._ended) {
|
72 | break;
|
73 | }
|
74 | else if (size == null) {
|
75 | const buffer = stream.read(2);
|
76 | if (buffer && buffer.length === 2) {
|
77 | size = buffer.readUint16LE();
|
78 | }
|
79 | else {
|
80 | break;
|
81 | }
|
82 | }
|
83 | else {
|
84 | const buffer = stream.read(size);
|
85 | if (buffer && buffer.length === size) {
|
86 | size = null;
|
87 | const message = JSON.parse(String(buffer));
|
88 | this._processMessage(message);
|
89 | }
|
90 | }
|
91 | }
|
92 | }
|
93 | catch (e) {
|
94 | this._processMessage({
|
95 | error: String(e)
|
96 | });
|
97 | }
|
98 | });
|
99 | }
|
100 | _listenForProcessExit(worker) {
|
101 | const errBuffer = [];
|
102 | worker.stderr.on("data", data => errBuffer.push(data));
|
103 | worker.on("exit", (code) => {
|
104 | let err = `Process ended prematurely. Exit code: ${code}`;
|
105 | if (errBuffer.length > 0) {
|
106 | err = `${err}. Error: ${Buffer.concat(errBuffer).toString()}`;
|
107 | }
|
108 | this._processMessage({
|
109 | error: err
|
110 | });
|
111 | });
|
112 | }
|
113 | }
|
114 | class Test {
|
115 | name;
|
116 | index;
|
117 | _callback;
|
118 | _setup;
|
119 | error = null;
|
120 | opMs = 0;
|
121 | totalTime = 0;
|
122 | samples = [];
|
123 | group = "";
|
124 | constructor(name, index, _callback, _setup) {
|
125 | this.name = name;
|
126 | this.index = index;
|
127 | this._callback = _callback;
|
128 | this._setup = _setup;
|
129 | }
|
130 | fork(benchName, processors, options) {
|
131 | return new Promise((resolve => {
|
132 | const forkContext = new ForkContext(this, processors, resolve, benchName, options);
|
133 | forkContext.start();
|
134 | }));
|
135 | }
|
136 | async run(setup) {
|
137 | (0, getDiff_1.getDiff)(1, this._callback, this._setup);
|
138 | let cycles = 1;
|
139 | let samples = setup.samples;
|
140 | while (samples > 0) {
|
141 | const diff = (0, getDiff_1.getDiff)(cycles, this._callback, this._setup);
|
142 | if (diff >= setup.time) {
|
143 | samples--;
|
144 | await Messager_1.Messager.send({
|
145 | diff: diff,
|
146 | cycles: cycles
|
147 | });
|
148 | }
|
149 | const ratio = diff > 0 ? (setup.time / diff) * 1.02 : 1.1;
|
150 | cycles = diff >= setup.time ? Math.round(cycles * ratio) : Math.ceil(cycles * ratio);
|
151 | }
|
152 | }
|
153 | }
|
154 | exports.Test = Test;
|