whet 0.1.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/bin/genes/util/EsMap.d.ts +1 -0
  2. package/bin/genes/util/EsMap.js +3 -0
  3. package/bin/haxe/Constraints.d.ts +1 -0
  4. package/bin/haxe/ds/IntMap.d.ts +6 -0
  5. package/bin/haxe/ds/IntMap.js +25 -0
  6. package/bin/haxe/ds/Vector.d.ts +2 -0
  7. package/bin/minimatch/MinimatchOptions.d.ts +28 -0
  8. package/bin/whet/Log.js +3 -0
  9. package/bin/whet/Project.d.ts +13 -0
  10. package/bin/whet/Project.js +26 -0
  11. package/bin/whet/Stone.d.ts +23 -0
  12. package/bin/whet/Stone.js +162 -7
  13. package/bin/whet/Whet.d.ts +1 -1
  14. package/bin/whet/Whet.js +68 -1
  15. package/bin/whet/cache/BaseCache.d.ts +7 -0
  16. package/bin/whet/cache/BaseCache.js +103 -7
  17. package/bin/whet/cache/CacheManager.d.ts +5 -0
  18. package/bin/whet/cache/CacheManager.js +97 -7
  19. package/bin/whet/cache/FileCache.d.ts +1 -0
  20. package/bin/whet/cache/FileCache.js +4 -0
  21. package/bin/whet/cache/MemoContext.d.ts +17 -0
  22. package/bin/whet/cache/MemoContext.js +35 -0
  23. package/bin/whet/magic/RoutePathType.js +5 -5
  24. package/bin/whet/profiler/Profiler.d.ts +65 -0
  25. package/bin/whet/profiler/Profiler.js +351 -0
  26. package/bin/whet/profiler/Span.d.ts +90 -0
  27. package/bin/whet/profiler/Span.js +56 -0
  28. package/bin/whet/profiler/SpanRecorder.d.ts +20 -0
  29. package/bin/whet/profiler/SpanRecorder.js +63 -0
  30. package/bin/whet/profiler/SpanStats.d.ts +15 -0
  31. package/bin/whet/profiler/SpanStats.js +49 -0
  32. package/bin/whet/route/Router.d.ts +5 -0
  33. package/bin/whet/route/Router.js +47 -33
  34. package/bin/whet/stones/Files.d.ts +5 -0
  35. package/bin/whet/stones/Files.js +20 -0
  36. package/bin/whet/stones/StoneFactory.d.ts +55 -0
  37. package/bin/whet/stones/StoneFactory.js +116 -0
  38. package/bin/whet.d.ts +2 -0
  39. package/bin/whet.js +1 -0
  40. package/package.json +2 -2
  41. package/bin/haxe/Log.d.ts +0 -33
  42. package/bin/haxe/Log.js +0 -61
  43. package/bin/pino_pretty/PrettyOptions.d.ts +0 -98
  44. package/bin/pino_pretty/default_/MessageFormatFunc.d.ts +0 -2
  45. package/bin/pino_pretty/default_/Prettifier.d.ts +0 -2
  46. package/bin/whet/extern/Minimatch.d.ts +0 -77
  47. package/bin/whet/stones/Server.d.ts +0 -59
  48. package/bin/whet/stones/Server.js +0 -261
@@ -0,0 +1,351 @@
1
+ import {SpanStats} from "./SpanStats.js"
2
+ import {SpanRecorder} from "./SpanRecorder.js"
3
+ import {Span, SpanEventType, SpanStatus} from "./Span.js"
4
+ import {AsyncLocalStorage} from "node:async_hooks"
5
+ import {IntMap} from "../../haxe/ds/IntMap.js"
6
+ import {EsMap} from "../../genes/util/EsMap.js"
7
+ import {Register} from "../../genes/Register.js"
8
+ import {Std} from "../../Std.js"
9
+ import {Reflect as Reflect__1} from "../../Reflect.js"
10
+ import {HxOverrides} from "../../HxOverrides.js"
11
+
12
+ const $global = Register.$global
13
+
14
+ export const Profiler = Register.global("$hxClasses")["whet.profiler.Profiler"] =
15
+ class Profiler extends Register.inherits() {
16
+ [Register.new](config) {
17
+ this.nextSpanId = 0;
18
+ this.listeners = [];
19
+ this.recorder = new SpanRecorder((config != null && config.maxSpans != null) ? config.maxSpans : 10000);
20
+ this.stats = new SpanStats();
21
+ this.context = new AsyncLocalStorage();
22
+ this.baseEpochUs = Date.now() * 1000;
23
+ this.basePerfUs = performance.now() * 1000;
24
+ }
25
+
26
+ /**
27
+ Primary API: wraps an async operation with timing and ALS context.
28
+ */
29
+ withSpan(stone, op, fn, meta) {
30
+ let parent = this.context.getStore();
31
+ let span = new Span(this.nextSpanId++, (parent != null) ? parent.id : null, stone.id, op, performance.now(), meta);
32
+ span.estimatedDuration = this.stats.getEstimate(stone.id, op);
33
+ this.emit(SpanEventType.Start, span);
34
+ let _gthis = this;
35
+ return this.context.run(span, function () {
36
+ return fn().then(function (result) {
37
+ span.endTime = performance.now();
38
+ span.duration = span.endTime - span.startTime;
39
+ span.status = SpanStatus.Ok;
40
+ _gthis.recorder.record(span);
41
+ _gthis.stats.update(stone.id, op, span.duration);
42
+ _gthis.emit(SpanEventType.End, span);
43
+ return result;
44
+ })["catch"](function (err) {
45
+ span.endTime = performance.now();
46
+ span.duration = span.endTime - span.startTime;
47
+ span.status = SpanStatus.Error(Std.string(err));
48
+ _gthis.recorder.record(span);
49
+ _gthis.emit(SpanEventType.End, span);
50
+ return Promise.reject(err);
51
+ });
52
+ });
53
+ }
54
+
55
+ /**
56
+ Secondary API: manual start for spans where no function can be wrapped (e.g. LockWait).
57
+ */
58
+ startSpan(stone, op, meta) {
59
+ let parent = this.context.getStore();
60
+ let span = new Span(this.nextSpanId++, (parent != null) ? parent.id : null, stone.id, op, performance.now(), meta);
61
+ span.estimatedDuration = this.stats.getEstimate(stone.id, op);
62
+ this.emit(SpanEventType.Start, span);
63
+ return span;
64
+ }
65
+
66
+ /**
67
+ Complete a manually started span.
68
+ */
69
+ endSpan(span) {
70
+ span.endTime = performance.now();
71
+ span.duration = span.endTime - span.startTime;
72
+ span.status = SpanStatus.Ok;
73
+ this.recorder.record(span);
74
+ this.stats.update(span.stone, span.operation, span.duration);
75
+ this.emit(SpanEventType.End, span);
76
+ }
77
+
78
+ /**
79
+ Returns the current span from AsyncLocalStorage context, or null if none.
80
+ */
81
+ getCurrentSpan() {
82
+ return this.context.getStore();
83
+ }
84
+
85
+ /**
86
+ Subscribe to span events. Returns unsubscribe function.
87
+ */
88
+ subscribe(listener) {
89
+ this.listeners.push(listener);
90
+ let _gthis = this;
91
+ return function () {
92
+ HxOverrides.remove(_gthis.listeners, listener);
93
+ };
94
+ }
95
+
96
+ /**
97
+ Export spans in the given format ("json" or "trace"). Defaults to "json".
98
+ */
99
+ export(format) {
100
+ if (format == "trace") {
101
+ return this.exportChromeTrace();
102
+ } else {
103
+ return this.exportJson();
104
+ };
105
+ }
106
+
107
+ /**
108
+ Return spans recorded since the given span ID (exclusive).
109
+ */
110
+ getSpansSince(sinceId) {
111
+ return this.recorder.getSpansSince(sinceId);
112
+ }
113
+
114
+ /**
115
+ Return aggregated profiling summary.
116
+ */
117
+ getSummary() {
118
+ let spans = this.recorder.getSpans();
119
+ let byStone = {};
120
+ let byOperation = {};
121
+ let cacheHits = 0;
122
+ let cacheLookups = 0;
123
+ let _g = 0;
124
+ while (_g < spans.length) {
125
+ let span = spans[_g];
126
+ ++_g;
127
+ let opKey = span.operation;
128
+ let opEntry = byOperation[opKey];
129
+ if (opEntry == null) {
130
+ opEntry = {"count": 0, "totalMs": 0.0};
131
+ byOperation[opKey] = opEntry;
132
+ };
133
+ opEntry.count++;
134
+ opEntry.totalMs += span.duration;
135
+ if (opKey == "Generate") {
136
+ Profiler.ensureStoneEntry(byStone, span.stone);
137
+ let entry = byStone[span.stone];
138
+ entry.generates++;
139
+ entry.totalDuration += span.duration;
140
+ entry.avgDuration = entry.totalDuration / entry.generates;
141
+ entry.lastDuration = span.duration;
142
+ };
143
+ if (span.metadata != null) {
144
+ let meta = span.metadata;
145
+ if (meta.cacheResult != null) {
146
+ ++cacheLookups;
147
+ if (meta.cacheResult == "hit") {
148
+ ++cacheHits;
149
+ Profiler.ensureStoneEntry(byStone, span.stone);
150
+ byStone[span.stone].cacheHits++;
151
+ };
152
+ };
153
+ };
154
+ };
155
+ return {"byStone": byStone, "byOperation": byOperation, "cacheHitRate": (cacheLookups > 0) ? cacheHits / cacheLookups : 0.0};
156
+ }
157
+ exportJson() {
158
+ let spans = this.recorder.getSpans();
159
+ let _g = [];
160
+ let _g1 = 0;
161
+ while (_g1 < spans.length) _g.push(this.serializeSpan(spans[_g1++]));
162
+ let stoneSet_inst = new Map();
163
+ let generateCount = 0;
164
+ let cacheHits = 0;
165
+ let cacheLookups = 0;
166
+ let _g2 = 0;
167
+ while (_g2 < spans.length) {
168
+ let span = spans[_g2];
169
+ ++_g2;
170
+ stoneSet_inst.set(span.stone, true);
171
+ if (span.operation == "Generate") {
172
+ ++generateCount;
173
+ };
174
+ if (span.metadata != null) {
175
+ let meta = span.metadata;
176
+ if (meta.cacheResult != null) {
177
+ ++cacheLookups;
178
+ if (meta.cacheResult == "hit") {
179
+ ++cacheHits;
180
+ };
181
+ };
182
+ };
183
+ };
184
+ let stoneCount = 0;
185
+ let _ = EsMap.adaptIterator(stoneSet_inst.values());
186
+ while (_.hasNext()) {
187
+ _.next();
188
+ ++stoneCount;
189
+ };
190
+ return {"spans": _g, "meta": {"spanCount": spans.length, "stoneCount": stoneCount, "totalGenerations": generateCount, "cacheHitRate": (cacheLookups > 0) ? cacheHits / cacheLookups : 0.0}};
191
+ }
192
+ exportChromeTrace() {
193
+ let spans = this.recorder.getSpans();
194
+ let spanById_inst = new Map();
195
+ let _g = 0;
196
+ while (_g < spans.length) {
197
+ let span = spans[_g];
198
+ ++_g;
199
+ spanById_inst.set(span.id, span);
200
+ };
201
+ let childrenOf_inst = new Map();
202
+ let roots = [];
203
+ let _g1 = 0;
204
+ while (_g1 < spans.length) {
205
+ let span = spans[_g1];
206
+ ++_g1;
207
+ let pid = span.parentId;
208
+ if (pid == null || !spanById_inst.has(pid)) {
209
+ roots.push(span);
210
+ } else {
211
+ if (!childrenOf_inst.has(pid)) {
212
+ childrenOf_inst.set(pid, []);
213
+ };
214
+ childrenOf_inst.get(pid).push(span);
215
+ };
216
+ };
217
+ let spanTid_inst = new Map();
218
+ let nextTid = 1;
219
+ let assignTids = null;
220
+ assignTids = function (span, tid) {
221
+ spanTid_inst.set(span.id, tid);
222
+ let children = childrenOf_inst.get(span.id);
223
+ if (children == null || children.length == 0) {
224
+ return;
225
+ };
226
+ children.sort(function (a, b) {
227
+ return Reflect__1.compare(a.startTime, b.startTime);
228
+ });
229
+ let laneEndTimes = [];
230
+ let laneTids = [];
231
+ let _g = 0;
232
+ while (_g < children.length) {
233
+ let child = children[_g];
234
+ ++_g;
235
+ let lane = -1;
236
+ let _g1 = 0;
237
+ let _g2 = laneEndTimes.length;
238
+ while (_g1 < _g2) {
239
+ let i = _g1++;
240
+ if (laneEndTimes[i] <= child.startTime) {
241
+ lane = i;
242
+ break;
243
+ };
244
+ };
245
+ if (lane == -1) {
246
+ lane = laneEndTimes.length;
247
+ let assignTids;
248
+ if (lane == 0) {
249
+ assignTids = tid;
250
+ } else {
251
+ nextTid += 1;
252
+ assignTids = nextTid - 1;
253
+ };
254
+ laneTids.push(assignTids);
255
+ laneEndTimes.push(child.endTime);
256
+ } else {
257
+ laneEndTimes[lane] = child.endTime;
258
+ };
259
+ assignTids(child, laneTids[lane]);
260
+ };
261
+ };
262
+ roots.sort(function (a, b) {
263
+ return Reflect__1.compare(a.startTime, b.startTime);
264
+ });
265
+ let _g2 = 0;
266
+ while (_g2 < roots.length) {
267
+ nextTid += 1;
268
+ assignTids(roots[_g2++], nextTid - 1);
269
+ };
270
+ let events = [];
271
+ let tidNames = new IntMap();
272
+ let _g3 = 0;
273
+ while (_g3 < spans.length) {
274
+ let span = spans[_g3];
275
+ ++_g3;
276
+ let tid = spanTid_inst.get(span.id);
277
+ if (tid != null && !tidNames.inst.has(tid)) {
278
+ tidNames.inst.set(tid, span.stone);
279
+ };
280
+ };
281
+ let map = tidNames;
282
+ let _g_keys = map.keys();
283
+ while (_g_keys.hasNext()) {
284
+ let key = _g_keys.next();
285
+ events.push({"ph": "M", "pid": 1, "tid": key, "name": "thread_name", "args": {"name": map.get(key)}});
286
+ };
287
+ let flowId = 0;
288
+ let _g4 = 0;
289
+ while (_g4 < spans.length) {
290
+ let span = spans[_g4];
291
+ ++_g4;
292
+ let tid = spanTid_inst.get(span.id);
293
+ if (tid == null) {
294
+ continue;
295
+ };
296
+ let ts = this.baseEpochUs + (span.startTime * 1000 - this.basePerfUs);
297
+ events.push({"ph": "X", "name": span.operation + " " + span.stone, "cat": "whet", "ts": ts, "dur": span.duration * 1000, "pid": 1, "tid": tid, "args": (span.metadata != null) ? span.metadata : {}});
298
+ if (span.parentId != null) {
299
+ let parent = spanById_inst.get(span.parentId);
300
+ if (parent != null) {
301
+ let parentTid = spanTid_inst.get(parent.id);
302
+ if (parentTid != null && parentTid != tid) {
303
+ events.push({"ph": "s", "id": flowId, "pid": 1, "tid": parentTid, "ts": this.baseEpochUs + (parent.startTime * 1000 - this.basePerfUs), "name": "trigger", "cat": "flow"});
304
+ events.push({"ph": "f", "bp": "e", "id": flowId, "pid": 1, "tid": tid, "ts": ts, "name": "trigger", "cat": "flow"});
305
+ ++flowId;
306
+ };
307
+ };
308
+ };
309
+ };
310
+ return {"traceEvents": events};
311
+ }
312
+ serializeSpan(span) {
313
+ let _g = span.status;
314
+ let tmp;
315
+ switch (_g._hx_index) {
316
+ case 0:
317
+ tmp = "ok";
318
+ break
319
+ case 1:
320
+ tmp = "error: " + _g.msg;
321
+ break
322
+
323
+ };
324
+ return {"id": span.id, "parentId": span.parentId, "stone": span.stone, "operation": span.operation, "startTime": span.startTime, "endTime": span.endTime, "duration": span.duration, "estimatedDuration": span.estimatedDuration, "metadata": span.metadata, "status": tmp};
325
+ }
326
+ emit(type, span) {
327
+ let event = {"type": type, "span": span};
328
+ let _g = 0;
329
+ let _g1 = this.listeners;
330
+ while (_g < _g1.length) _g1[_g++](event);
331
+ }
332
+ static ensureStoneEntry(byStone, stone) {
333
+ if (!Object.prototype.hasOwnProperty.call(byStone, stone)) {
334
+ byStone[stone] = {"generates": 0, "totalDuration": 0.0, "avgDuration": 0.0, "lastDuration": 0.0, "cacheHits": 0};
335
+ };
336
+ }
337
+ static get __name__() {
338
+ return "whet.profiler.Profiler"
339
+ }
340
+ get __class__() {
341
+ return Profiler
342
+ }
343
+ }
344
+ Profiler.prototype.recorder = null;
345
+ Profiler.prototype.stats = null;
346
+ Profiler.prototype.listeners = null;
347
+ Profiler.prototype.context = null;
348
+ Profiler.prototype.baseEpochUs = null;
349
+ Profiler.prototype.basePerfUs = null;
350
+ Profiler.prototype.nextSpanId = null;
351
+
@@ -0,0 +1,90 @@
1
+
2
+ export declare class Span<T> {
3
+ constructor(id: number, parentId: null | number, stone: string, op: string, startTime: number, metadata?: null | T)
4
+ id: number
5
+ parentId: null | number
6
+ stone: string
7
+ operation: string
8
+ startTime: number
9
+ endTime: number
10
+ duration: number
11
+ estimatedDuration: number
12
+ metadata: T
13
+ status: SpanStatus
14
+ }
15
+
16
+ export type AnySpan = Span<any>
17
+
18
+ export declare namespace SpanStatus {
19
+ export type Ok = {_hx_index: 0, __enum__: "whet.profiler.SpanStatus"}
20
+ export const Ok: Ok
21
+ export type Error = {_hx_index: 1, msg: string, __enum__: "whet.profiler.SpanStatus"}
22
+ export const Error: (msg: string) => SpanStatus
23
+ }
24
+
25
+ export declare type SpanStatus =
26
+ | SpanStatus.Ok
27
+ | SpanStatus.Error
28
+
29
+ export declare namespace SpanEventType {
30
+ export type Start = {_hx_index: 0, __enum__: "whet.profiler.SpanEventType"}
31
+ export const Start: Start
32
+ export type End = {_hx_index: 1, __enum__: "whet.profiler.SpanEventType"}
33
+ export const End: End
34
+ }
35
+
36
+ export declare type SpanEventType =
37
+ | SpanEventType.Start
38
+ | SpanEventType.End
39
+
40
+ export type SpanEvent = {
41
+ span: AnySpan,
42
+ type: SpanEventType
43
+ }
44
+
45
+ /**
46
+ Metadata types per span operation.
47
+ */
48
+ export type LockWaitMeta = {
49
+ queueLength?: null | number,
50
+ queuePosition?: null | number
51
+ }
52
+
53
+ export type LockHeldMeta = {
54
+ cacheResult?: null | string
55
+ }
56
+
57
+ export type HashMeta = {
58
+ dependencyCount?: null | number,
59
+ hashHex?: null | string
60
+ }
61
+
62
+ export type GenerateMeta = {
63
+ outputCount?: null | number,
64
+ totalBytes?: null | number
65
+ }
66
+
67
+ export type GeneratePartialMeta = {
68
+ outputBytes?: null | number,
69
+ sourceId?: null | string
70
+ }
71
+
72
+ export type DepResolveMeta = {
73
+ dependencyIds?: null | string[]
74
+ }
75
+
76
+ export type CacheWriteMeta = {
77
+ entryCount?: null | number,
78
+ strategy?: null | string
79
+ }
80
+
81
+ export type ListMeta = {
82
+ resultCount?: null | number
83
+ }
84
+
85
+ export type ServeMeta = {
86
+ method?: null | string,
87
+ path?: null | string,
88
+ responseBytes?: null | number,
89
+ statusCode?: null | number
90
+ }
@@ -0,0 +1,56 @@
1
+ import {Register} from "../../genes/Register.js"
2
+
3
+ const $global = Register.$global
4
+
5
+ export const Span = Register.global("$hxClasses")["whet.profiler.Span"] =
6
+ class Span extends Register.inherits() {
7
+ [Register.new](id, parentId, stone, op, startTime, metadata) {
8
+ this.id = id;
9
+ this.parentId = parentId;
10
+ this.stone = stone;
11
+ this.operation = op;
12
+ this.startTime = startTime;
13
+ this.metadata = metadata;
14
+ this.estimatedDuration = 0;
15
+ this.status = SpanStatus.Ok;
16
+ }
17
+ static get __name__() {
18
+ return "whet.profiler.Span"
19
+ }
20
+ get __class__() {
21
+ return Span
22
+ }
23
+ }
24
+ Span.prototype.id = null;
25
+ Span.prototype.parentId = null;
26
+ Span.prototype.stone = null;
27
+ Span.prototype.operation = null;
28
+ Span.prototype.startTime = null;
29
+ Span.prototype.endTime = null;
30
+ Span.prototype.duration = null;
31
+ Span.prototype.estimatedDuration = null;
32
+ Span.prototype.metadata = null;
33
+ Span.prototype.status = null;
34
+
35
+
36
+ export const SpanStatus =
37
+ Register.global("$hxEnums")["whet.profiler.SpanStatus"] =
38
+ {
39
+ __ename__: "whet.profiler.SpanStatus",
40
+
41
+ Ok: {_hx_name: "Ok", _hx_index: 0, __enum__: "whet.profiler.SpanStatus"},
42
+ Error: Object.assign((msg) => ({_hx_index: 1, __enum__: "whet.profiler.SpanStatus", "msg": msg}), {_hx_name: "Error", __params__: ["msg"]})
43
+ }
44
+ SpanStatus.__constructs__ = [SpanStatus.Ok, SpanStatus.Error]
45
+ SpanStatus.__empty_constructs__ = [SpanStatus.Ok]
46
+
47
+ export const SpanEventType =
48
+ Register.global("$hxEnums")["whet.profiler.SpanEventType"] =
49
+ {
50
+ __ename__: "whet.profiler.SpanEventType",
51
+
52
+ Start: {_hx_name: "Start", _hx_index: 0, __enum__: "whet.profiler.SpanEventType"},
53
+ End: {_hx_name: "End", _hx_index: 1, __enum__: "whet.profiler.SpanEventType"}
54
+ }
55
+ SpanEventType.__constructs__ = [SpanEventType.Start, SpanEventType.End]
56
+ SpanEventType.__empty_constructs__ = [SpanEventType.Start, SpanEventType.End]
@@ -0,0 +1,20 @@
1
+ import {AnySpan} from "./Span"
2
+
3
+ export declare class SpanRecorder {
4
+ constructor(maxSize: number)
5
+ maxSize: number
6
+ totalCount: number
7
+ protected buffer: AnySpan[]
8
+ protected writeIndex: number
9
+ record(span: AnySpan): void
10
+
11
+ /**
12
+ Returns all recorded spans in chronological order.
13
+ */
14
+ getSpans(): AnySpan[]
15
+
16
+ /**
17
+ Returns spans recorded since the given span ID (exclusive).
18
+ */
19
+ getSpansSince(sinceId: number): AnySpan[]
20
+ }
@@ -0,0 +1,63 @@
1
+ import {Register} from "../../genes/Register.js"
2
+
3
+ const $global = Register.$global
4
+
5
+ export const SpanRecorder = Register.global("$hxClasses")["whet.profiler.SpanRecorder"] =
6
+ class SpanRecorder extends Register.inherits() {
7
+ [Register.new](maxSize) {
8
+ this.writeIndex = 0;
9
+ this.totalCount = 0;
10
+ this.maxSize = maxSize;
11
+ this.buffer = new Array(maxSize);
12
+ }
13
+ record(span) {
14
+ this.buffer[this.writeIndex % this.maxSize] = span;
15
+ this.writeIndex++;
16
+ this.totalCount++;
17
+ }
18
+
19
+ /**
20
+ Returns all recorded spans in chronological order.
21
+ */
22
+ getSpans() {
23
+ let count = (this.writeIndex < this.maxSize) ? this.writeIndex : this.maxSize;
24
+ let result = new Array();
25
+ result.length = count;
26
+ let start = (this.writeIndex < this.maxSize) ? 0 : this.writeIndex % this.maxSize;
27
+ let _g = 0;
28
+ let _g1 = count;
29
+ while (_g < _g1) {
30
+ let i = _g++;
31
+ result[i] = this.buffer[(start + i) % this.maxSize];
32
+ };
33
+ return result;
34
+ }
35
+
36
+ /**
37
+ Returns spans recorded since the given span ID (exclusive).
38
+ */
39
+ getSpansSince(sinceId) {
40
+ let all = this.getSpans();
41
+ let result = [];
42
+ let _g = 0;
43
+ while (_g < all.length) {
44
+ let span = all[_g];
45
+ ++_g;
46
+ if (span.id > sinceId) {
47
+ result.push(span);
48
+ };
49
+ };
50
+ return result;
51
+ }
52
+ static get __name__() {
53
+ return "whet.profiler.SpanRecorder"
54
+ }
55
+ get __class__() {
56
+ return SpanRecorder
57
+ }
58
+ }
59
+ SpanRecorder.prototype.maxSize = null;
60
+ SpanRecorder.prototype.totalCount = null;
61
+ SpanRecorder.prototype.buffer = null;
62
+ SpanRecorder.prototype.writeIndex = null;
63
+
@@ -0,0 +1,15 @@
1
+ import {Map as Map__1} from "../../Map"
2
+
3
+ export declare class SpanStats {
4
+ constructor()
5
+ protected data: Map__1<string, StatEntry>
6
+ getEstimate(stoneId: string, op: string): number
7
+ update(stoneId: string, op: string, duration: number): void
8
+ getSummary(): any
9
+ }
10
+
11
+ export type StatEntry = {
12
+ count: number,
13
+ lastDuration: number,
14
+ totalDuration: number
15
+ }
@@ -0,0 +1,49 @@
1
+ import {StringMap} from "../../haxe/ds/StringMap.js"
2
+ import {Register} from "../../genes/Register.js"
3
+
4
+ const $global = Register.$global
5
+
6
+ export const SpanStats = Register.global("$hxClasses")["whet.profiler.SpanStats"] =
7
+ class SpanStats extends Register.inherits() {
8
+ [Register.new]() {
9
+ this.data = new StringMap();
10
+ }
11
+ getEstimate(stoneId, op) {
12
+ let entry = this.data.inst.get("" + stoneId + ":" + op);
13
+ if (entry != null) {
14
+ return entry.lastDuration;
15
+ } else {
16
+ return 0;
17
+ };
18
+ }
19
+ update(stoneId, op, duration) {
20
+ let key = "" + stoneId + ":" + op;
21
+ let entry = this.data.inst.get(key);
22
+ if (entry == null) {
23
+ this.data.inst.set(key, {"lastDuration": duration, "totalDuration": duration, "count": 1});
24
+ } else {
25
+ entry.lastDuration = duration;
26
+ entry.totalDuration += duration;
27
+ entry.count++;
28
+ };
29
+ }
30
+ getSummary() {
31
+ let result = {};
32
+ let this1 = this.data;
33
+ let _g_keys = this1.keys();
34
+ while (_g_keys.hasNext()) {
35
+ let key = _g_keys.next();
36
+ let _g_value = this1.get(key);
37
+ result[key] = {"lastDuration": _g_value.lastDuration, "avgDuration": _g_value.totalDuration / _g_value.count, "count": _g_value.count};
38
+ };
39
+ return result;
40
+ }
41
+ static get __name__() {
42
+ return "whet.profiler.SpanStats"
43
+ }
44
+ get __class__() {
45
+ return SpanStats
46
+ }
47
+ }
48
+ SpanStats.prototype.data = null;
49
+
@@ -11,6 +11,11 @@ export declare class Router {
11
11
  protected routes: RoutePath[]
12
12
  route(r: RoutePathType): void
13
13
 
14
+ /**
15
+ Remove all routes.
16
+ */
17
+ clearRoutes(): void
18
+
14
19
  /**
15
20
  Recursively collect all Stone IDs referenced in this Router's routes.
16
21
  */