@universal-packages/time-measurer 1.5.0 → 2.0.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.
package/README.md CHANGED
@@ -6,108 +6,466 @@
6
6
 
7
7
  Time Measurer is a simple wrap for `process.hrtime.bigint` to measure time with procession and express that time easily through formatted representations, anytime you want to express how much a query or a request took at code level you may want to give this a try.
8
8
 
9
- ## Install
9
+ # Getting Started
10
10
 
11
11
  ```shell
12
12
  npm install @universal-packages/time-measurer
13
13
  ```
14
14
 
15
- ## Global methods
15
+ # Usage
16
16
 
17
- #### **`startMeasurement()`**
17
+ ## TimeMeasurer `class`
18
18
 
19
- Creates a new TimeMeasurer instance to start a measurement.
19
+ The `TimeMeasurer` class is a simple utility for measuring time with precision. It wraps `process.hrtime.bigint()` for Node.js environments and falls back to `performance.now()` in browser environments.
20
20
 
21
21
  ```ts
22
- import { startMeasurement } from '@universal-packages/time-measurer'
22
+ import { TimeMeasurer } from '@universal-packages/time-measurer'
23
23
 
24
- async function getAll() {
25
- const measurer = startMeasurement()
26
- const data = await myDB.getAllRecords()
27
- const measurement = measurer.finish()
24
+ const measurer = TimeMeasurer.start()
25
+ // ... some operation
26
+ const measurement = measurer.finish()
28
27
 
29
- console.log('All records - ', measurement.toString())
30
- }
28
+ console.log(measurement.toString()) // "123.456ms"
29
+ ```
31
30
 
32
- getAll()
33
- // > All records - 2.23ms
31
+ ### Constructor <small><small>`constructor`</small></small>
32
+
33
+ ```ts
34
+ new TimeMeasurer()
34
35
  ```
35
36
 
36
- #### **`sleep(milliseconds: number)`**
37
+ Creates a new TimeMeasurer instance. The measurer is not started automatically.
37
38
 
38
- Time measurer ships with a convenient sleep function that takes a single parameter `time` in milliseconds, internally it is just a promise with a timeout that resolves it.
39
+ ### Instance Methods
39
40
 
40
- ```js
41
- import { sleep } from '@universal-packages/time-measurer'
41
+ #### start
42
42
 
43
- async function awaitable() {
44
- await sleep(2000)
45
- }
43
+ ```ts
44
+ start(): void
46
45
  ```
47
46
 
48
- ## TimeMeasurer
47
+ Starts the time measurement. This method will throw an error if the measurer has already been started.
48
+
49
+ ```ts
50
+ const measurer = new TimeMeasurer()
51
+ measurer.start()
52
+ // ... some operation
53
+ const measurement = measurer.finish()
54
+ ```
49
55
 
50
- Class `TimeMeasurer` provides an instantiable interface to start measuring time from any part of your code. The measurement starts at instancing time.
56
+ #### finish
51
57
 
52
- ```js
53
- import { TimeMeasurer } from '@universal-packages/time-measurer'
58
+ ```ts
59
+ finish(): Measurement
60
+ ```
61
+
62
+ Finishes the time measurement and returns a `Measurement` instance containing the elapsed time.
54
63
 
55
- async function getAll() {
56
- const measurer = new TimeMeasurer()
64
+ ```ts
65
+ const measurer = new TimeMeasurer()
66
+ measurer.start()
67
+ // ... some operation
68
+ const measurement = measurer.finish()
69
+ ```
57
70
 
58
- measurer.start()
71
+ ### Static Methods
59
72
 
60
- const data = await myDB.getAllRecords()
61
- const measurement = measurer.finish()
73
+ #### start
62
74
 
63
- console.log('All records - ', measurement.toString())
64
- }
75
+ ```ts
76
+ static start(): TimeMeasurer
77
+ ```
78
+
79
+ Creates a new TimeMeasurer instance and immediately starts it. This is a convenience method for quick measurements.
80
+
81
+ ```ts
82
+ const measurer = TimeMeasurer.start()
83
+ // ... some operation
84
+ const measurement = measurer.finish()
85
+ ```
86
+
87
+ ## Measurement `class`
88
+
89
+ The `Measurement` class represents a measured time duration with various formatting options and convenient accessors for different time units.
90
+
91
+ ```ts
92
+ import { Measurement, TimeMeasurer } from '@universal-packages/time-measurer'
93
+
94
+ const measurer = TimeMeasurer.start()
95
+ // ... some operation
96
+ const measurement = measurer.finish()
97
+
98
+ console.log(measurement.hours) // 0
99
+ console.log(measurement.minutes) // 0
100
+ console.log(measurement.seconds) // 1
101
+ console.log(measurement.milliseconds) // 234.567
102
+ ```
103
+
104
+ ### Constructor <small><small>`constructor`</small></small>
105
+
106
+ ```ts
107
+ new Measurement(nanoseconds: bigint)
108
+ ```
109
+
110
+ Creates a new Measurement instance from nanoseconds. This is typically called internally by TimeMeasurer.
111
+
112
+ ### Properties
113
+
114
+ - **`hours`**: `number` - The hours component of the measurement
115
+ - **`minutes`**: `number` - The minutes component of the measurement
116
+ - **`seconds`**: `number` - The seconds component of the measurement
117
+ - **`milliseconds`**: `number` - The milliseconds component (including fractional part)
118
+
119
+ ### Instance Methods
120
+
121
+ #### toString
122
+
123
+ ```ts
124
+ toString(format?: TimeFormat): string
125
+ ```
126
+
127
+ Converts the measurement to a formatted string representation.
128
+
129
+ ```ts
130
+ const measurement = new Measurement(1234567890n)
131
+
132
+ console.log(measurement.toString('Human')) // "1.234sec"
133
+ console.log(measurement.toString('Condensed')) // "1.234"
134
+ console.log(measurement.toString('Expressive')) // "1.234 Seconds"
135
+ ```
136
+
137
+ ##### TimeFormat
138
+
139
+ - **`'Human'`** (default): User-friendly format like "1.234sec", "2min 30.500sec", "1hrs 15min 30.250sec"
140
+ - **`'Condensed'`**: Compact format like "1.234", "02:30.500", "01:15:30.250"
141
+ - **`'Expressive'`**: Verbose format like "1.234 Seconds", "2 Minutes, and 30.500 Seconds"
142
+
143
+ #### toDate
144
+
145
+ ```ts
146
+ toDate(): Date
147
+ ```
148
+
149
+ Converts the measurement to a JavaScript Date object with the time components.
150
+
151
+ ```ts
152
+ const measurement = new Measurement(3661000000000n) // 1 hour, 1 minute, 1 second
153
+ const date = measurement.toDate()
154
+ console.log(date.getHours()) // 1
155
+ console.log(date.getMinutes()) // 1
156
+ console.log(date.getSeconds()) // 1
157
+ ```
158
+
159
+ ## Benchmark `class`
160
+
161
+ The `Benchmark` class provides functionality for running performance benchmarks with support for multiple iterations, warmup runs, and statistical analysis.
162
+
163
+ ```ts
164
+ import { Benchmark } from '@universal-packages/time-measurer'
165
+
166
+ const benchmark = new Benchmark({
167
+ iterations: 1000,
168
+ warmupIterations: 100,
169
+ name: 'Array sorting benchmark'
170
+ })
171
+
172
+ const result = benchmark.run(() => {
173
+ const arr = Array.from({ length: 1000 }, () => Math.random())
174
+ arr.sort()
175
+ })
176
+
177
+ console.log(`Average: ${result.average.toString()}`)
178
+ console.log(`Min: ${result.min.toString()}`)
179
+ console.log(`Max: ${result.max.toString()}`)
180
+ ```
181
+
182
+ ### Constructor <small><small>`constructor`</small></small>
183
+
184
+ ```ts
185
+ new Benchmark(options?: BenchmarkOptions)
186
+ ```
187
+
188
+ Creates a new Benchmark instance with the specified options.
189
+
190
+ #### BenchmarkOptions
191
+
192
+ - **`iterations`**: `number` (default: `1`)
193
+ Number of iterations to run for the actual benchmark measurement.
194
+ - **`warmupIterations`**: `number` (default: `0`)
195
+ Number of warmup iterations to run before the actual measurement to stabilize performance.
196
+ - **`name`**: `string` (default: `'Unnamed Benchmark'`)
197
+ A descriptive name for the benchmark.
198
+
199
+ ### Instance Methods
200
+
201
+ #### run
202
+
203
+ ```ts
204
+ run(fn: () => void): BenchmarkResult
205
+ ```
206
+
207
+ Runs a synchronous function benchmark and returns detailed results including statistics.
208
+
209
+ ```ts
210
+ const benchmark = new Benchmark({ iterations: 100 })
211
+
212
+ const result = benchmark.run(() => {
213
+ // Your code to benchmark
214
+ heavyComputation()
215
+ })
216
+
217
+ console.log(`Completed ${result.iterations} iterations`)
218
+ console.log(`Average time: ${result.average.toString()}`)
219
+ ```
220
+
221
+ #### runAsync
222
+
223
+ ```ts
224
+ runAsync(fn: () => Promise<void>): Promise<BenchmarkResult>
225
+ ```
226
+
227
+ Runs an asynchronous function benchmark and returns detailed results including statistics.
228
+
229
+ ```ts
230
+ const benchmark = new Benchmark({ iterations: 50 })
231
+
232
+ const result = await benchmark.runAsync(async () => {
233
+ // Your async code to benchmark
234
+ await asyncOperation()
235
+ })
236
+
237
+ console.log(`Average time: ${result.average.toString()}`)
238
+ ```
239
+
240
+ #### BenchmarkResult
241
+
242
+ The result object returned by `run()` and `runAsync()` contains:
243
+
244
+ - **`name`**: `string` - Name of the benchmark
245
+ - **`iterations`**: `number` - Number of iterations performed
246
+ - **`warmupIterations`**: `number` - Number of warmup iterations performed
247
+ - **`measurements`**: `Measurement[]` - Array of all individual measurements
248
+ - **`min`**: `Measurement` - Fastest measurement
249
+ - **`max`**: `Measurement` - Slowest measurement
250
+ - **`average`**: `Measurement` - Average of all measurements
251
+ - **`total`**: `Measurement` - Total time for all iterations
65
252
 
66
- getAll()
67
- // > All records - 2.23ms
253
+ ## TimeProfiler `class`
254
+
255
+ The `TimeProfiler` class provides advanced profiling capabilities with named checkpoints, memory tracking, and session management for detailed performance analysis.
256
+
257
+ ```ts
258
+ import { TimeProfiler } from '@universal-packages/time-measurer'
259
+
260
+ const profiler = TimeProfiler.start('Database Operations')
261
+
262
+ // Start some operation
263
+ const users = await db.users.findMany()
264
+ profiler.checkpoint('Users loaded')
265
+
266
+ // Another operation
267
+ const posts = await db.posts.findMany()
268
+ profiler.checkpoint('Posts loaded')
269
+
270
+ // Finish profiling
271
+ const checkpoints = profiler.stop('Complete')
272
+
273
+ checkpoints.forEach((cp) => {
274
+ console.log(`${cp.name}: ${cp.measurement.toString()}`)
275
+ })
276
+ ```
277
+
278
+ ### Constructor <small><small>`constructor`</small></small>
279
+
280
+ ```ts
281
+ new TimeProfiler(options?: ProfilerOptions)
68
282
  ```
69
283
 
70
- ### Instance methods
284
+ Creates a new TimeProfiler instance with the specified options.
71
285
 
72
- #### **`start()`**
286
+ #### ProfilerOptions
73
287
 
74
- Resets the initial time.
288
+ - **`name`**: `string` (default: `'Profiler Session'`)
289
+ A descriptive name for the profiling session.
290
+ - **`trackMemory`**: `boolean` (default: `false`)
291
+ Whether to track memory usage and deltas between checkpoints.
75
292
 
76
- #### **`stop()`**
293
+ ### Properties
77
294
 
78
- Returns a measurement representing the time passed from when start was called.
295
+ #### checkpoints
79
296
 
80
- ## Measurement
297
+ ```ts
298
+ readonly checkpoints: ProfilerCheckpoint[]
299
+ ```
81
300
 
82
- A `Measurement` object is the time representation after a measure, it provides the interface to express time as a formatted string or even as a date object.
301
+ Returns a copy of all checkpoints recorded so far.
83
302
 
84
- ### Instance methods
303
+ #### lastCheckpoint
85
304
 
86
- #### **`toString(format: TimeFormat)`**
305
+ ```ts
306
+ readonly lastCheckpoint: ProfilerCheckpoint | undefined
307
+ ```
87
308
 
88
- Get the time representation as a string, this function takes one param `TimeFormat`, that can be one of `Condensed`, `Human`, `Expressive`, default: `Human`.
309
+ Returns the most recently recorded checkpoint, or undefined if none exist.
89
310
 
90
- Example output
311
+ #### isRunning
91
312
 
313
+ ```ts
314
+ readonly isRunning: boolean
92
315
  ```
93
- 2hrs 35min 51.235sec
94
- 2:35:51.235
95
- 2hrs 35min 51.235sec
96
- 2 Hours, 35 Minutes, and 51.235 Seconds
316
+
317
+ Returns true if the profiler is currently active and measuring time.
318
+
319
+ #### elapsed
320
+
321
+ ```ts
322
+ readonly elapsed: Measurement | undefined
97
323
  ```
98
324
 
99
- It will take into account parts of the representation that are not contributing to the time, like if the measurement only took seconds, minutes and hours will not be included.
325
+ Returns the current elapsed time since the profiler was started, or undefined if not started.
100
326
 
327
+ ### Instance Methods
328
+
329
+ #### start
330
+
331
+ ```ts
332
+ start(): void
101
333
  ```
102
- 51.235sec
103
- 51.235
104
- 51.235sec
105
- 51.235 Seconds
334
+
335
+ Starts the profiling session. Throws an error if already started.
336
+
337
+ ```ts
338
+ const profiler = new TimeProfiler()
339
+ profiler.start()
340
+ ```
341
+
342
+ #### checkpoint
343
+
344
+ ```ts
345
+ checkpoint(name: string): Measurement
346
+ ```
347
+
348
+ Creates a named checkpoint and returns the measurement from the start time. Throws an error if not started.
349
+
350
+ ```ts
351
+ profiler.checkpoint('Database connected')
352
+ // ... more operations
353
+ profiler.checkpoint('Data processed')
354
+ ```
355
+
356
+ #### getCheckpoint
357
+
358
+ ```ts
359
+ getCheckpoint(name: string): ProfilerCheckpoint | undefined
360
+ ```
361
+
362
+ Retrieves a specific checkpoint by name.
363
+
364
+ ```ts
365
+ const dbCheckpoint = profiler.getCheckpoint('Database connected')
366
+ if (dbCheckpoint) {
367
+ console.log(`DB connection took: ${dbCheckpoint.measurement.toString()}`)
368
+ }
369
+ ```
370
+
371
+ #### stop
372
+
373
+ ```ts
374
+ stop(finalCheckpointName?: string): ProfilerCheckpoint[]
375
+ ```
376
+
377
+ Stops the profiler, creates a final checkpoint, and returns all checkpoints.
378
+
379
+ ```ts
380
+ const allCheckpoints = profiler.stop('Session Complete')
381
+ ```
382
+
383
+ #### reset
384
+
385
+ ```ts
386
+ reset(): void
387
+ ```
388
+
389
+ Resets the profiler state to start a new session.
390
+
391
+ ```ts
392
+ profiler.reset()
393
+ profiler.start() // Ready for a new session
394
+ ```
395
+
396
+ ### Static Methods
397
+
398
+ #### start
399
+
400
+ ```ts
401
+ static start(name?: string): TimeProfiler
402
+ ```
403
+
404
+ Creates and immediately starts a new TimeProfiler instance.
405
+
406
+ ```ts
407
+ const profiler = TimeProfiler.start('API Request Processing')
408
+ ```
409
+
410
+ #### ProfilerCheckpoint
411
+
412
+ Each checkpoint contains:
413
+
414
+ - **`name`**: `string` - Name/label for the checkpoint
415
+ - **`measurement`**: `Measurement` - Time elapsed from start to this checkpoint
416
+ - **`timestamp`**: `Date` - When the checkpoint was created
417
+ - **`memoryUsage`**: `number` (optional) - Memory usage in bytes (if tracking enabled)
418
+ - **`memoryDelta`**: `number` (optional) - Memory change from previous checkpoint (if tracking enabled)
419
+
420
+ ### Memory Tracking Example
421
+
422
+ ```ts
423
+ const profiler = new TimeProfiler({ trackMemory: true })
424
+ profiler.start()
425
+
426
+ // Create some data
427
+ const largeArray = new Array(1000000).fill('data')
428
+ const checkpoint1 = profiler.checkpoint('Array created')
429
+
430
+ // Process data
431
+ largeArray.forEach((item) => item.toUpperCase())
432
+ const checkpoint2 = profiler.checkpoint('Array processed')
433
+
434
+ console.log(`Memory at checkpoint 1: ${checkpoint1.memoryUsage} bytes`)
435
+ console.log(`Memory delta: ${checkpoint2.memoryDelta} bytes`)
436
+ ```
437
+
438
+ ## Sleep `class`
439
+
440
+ The `Sleep` class provides a simple utility for creating delays in asynchronous code using human-readable time strings. It leverages the `ms` library for flexible time string parsing.
441
+
442
+ ```ts
443
+ import { Sleep } from '@universal-packages/time-measurer'
444
+
445
+ // Wait for 2 seconds
446
+ await Sleep.for('2s')
447
+
448
+ // Wait for 1.5 seconds
449
+ await Sleep.for('1500ms')
450
+
451
+ // Wait for 2 minutes
452
+ await Sleep.for('2m')
453
+
454
+ // Wait for 1 hour
455
+ await Sleep.for('1h')
456
+ ```
457
+
458
+ ### Static Methods
459
+
460
+ #### for
461
+
462
+ ```ts
463
+ static for(timeString: StringValue): Promise<void>
106
464
  ```
107
465
 
108
- #### **`toDate()`**
466
+ Creates a delay for the specified duration using a human-readable time string. Returns a Promise that resolves after the specified time has elapsed.
109
467
 
110
- Get the time representation as a date object this can be helpful if you want to use the `Date` api to format or do whatever with the date.
468
+ The `timeString` parameter accepts the same format as the `ms` library
111
469
 
112
470
  ## Typescript
113
471
 
package/Sleep.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { StringValue } from 'ms';
2
+ export declare class Sleep {
3
+ static for(timeString: StringValue): Promise<void>;
4
+ }
5
+ //# sourceMappingURL=Sleep.d.ts.map
package/Sleep.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sleep.d.ts","sourceRoot":"","sources":["../src/Sleep.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAEpC,qBAAa,KAAK;WACI,GAAG,CAAC,UAAU,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAIhE"}
package/Sleep.js ADDED
@@ -0,0 +1,8 @@
1
+ import ms from 'ms';
2
+ export class Sleep {
3
+ static async for(timeString) {
4
+ const duration = ms(timeString);
5
+ return new Promise((resolve) => setTimeout(resolve, duration));
6
+ }
7
+ }
8
+ //# sourceMappingURL=Sleep.js.map
package/Sleep.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sleep.js","sourceRoot":"","sources":["../src/Sleep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,IAAI,CAAA;AAEpC,MAAM,OAAO,KAAK;IACT,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAuB;QAC7C,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,CAAA;QAC/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAA;IAChE,CAAC;CACF"}
package/TimeMeasurer.d.ts CHANGED
@@ -1,15 +1,20 @@
1
- import Measurement from './Measurement';
2
- /**
3
- *
4
- * It measures the time a process takes from the time start is called
5
- * to when the finish method is called
6
- *
7
- */
8
- export default class TimeMeasurer {
1
+ import { Measurement } from './Measurement';
2
+ export declare class TimeMeasurer {
9
3
  private hrStart;
10
4
  private startTime;
11
- /** Resets the initial time */
5
+ /**
6
+ * Start a new measurer
7
+ * @returns Measurer instance
8
+ */
9
+ static start(): TimeMeasurer;
10
+ /**
11
+ * Start the measurer
12
+ */
12
13
  start(): void;
13
- /** Returns a measurement representing the time passed from when start was called */
14
+ /**
15
+ * Finish the measurer
16
+ * @returns Measurement instance
17
+ */
14
18
  finish(): Measurement;
15
19
  }
20
+ //# sourceMappingURL=TimeMeasurer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimeMeasurer.d.ts","sourceRoot":"","sources":["../src/TimeMeasurer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,SAAS,CAAY;IAE7B;;;OAGG;WACW,KAAK,IAAI,YAAY;IAMnC;;OAEG;IACI,KAAK,IAAI,IAAI;IAYpB;;;OAGG;IACI,MAAM,IAAI,WAAW;CAW7B"}
package/TimeMeasurer.js CHANGED
@@ -1,22 +1,23 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const Measurement_1 = __importDefault(require("./Measurement"));
7
- /**
8
- *
9
- * It measures the time a process takes from the time start is called
10
- * to when the finish method is called
11
- *
12
- */
13
- class TimeMeasurer {
14
- constructor() {
15
- this.hrStart = 0n;
16
- this.startTime = 0;
1
+ import { Measurement } from './Measurement';
2
+ export class TimeMeasurer {
3
+ hrStart = 0n;
4
+ startTime = 0;
5
+ /**
6
+ * Start a new measurer
7
+ * @returns Measurer instance
8
+ */
9
+ static start() {
10
+ const measurer = new TimeMeasurer();
11
+ measurer.start();
12
+ return measurer;
17
13
  }
18
- /** Resets the initial time */
14
+ /**
15
+ * Start the measurer
16
+ */
19
17
  start() {
18
+ if (this.hrStart || this.startTime) {
19
+ throw new Error('Measurer already started');
20
+ }
20
21
  if (typeof process !== 'undefined' && process.hrtime) {
21
22
  this.hrStart = process.hrtime.bigint();
22
23
  }
@@ -24,7 +25,10 @@ class TimeMeasurer {
24
25
  this.startTime = performance.now();
25
26
  }
26
27
  }
27
- /** Returns a measurement representing the time passed from when start was called */
28
+ /**
29
+ * Finish the measurer
30
+ * @returns Measurement instance
31
+ */
28
32
  finish() {
29
33
  let nanoseconds;
30
34
  if (typeof process !== 'undefined' && process.hrtime) {
@@ -34,8 +38,7 @@ class TimeMeasurer {
34
38
  const milliseconds = performance.now() - this.startTime;
35
39
  nanoseconds = BigInt(Math.round(milliseconds * 1e6));
36
40
  }
37
- return new Measurement_1.default(nanoseconds);
41
+ return new Measurement(nanoseconds);
38
42
  }
39
43
  }
40
- exports.default = TimeMeasurer;
41
44
  //# sourceMappingURL=TimeMeasurer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeMeasurer.js","sourceRoot":"","sources":["../src/TimeMeasurer.ts"],"names":[],"mappings":";;;;;AAAA,gEAAuC;AAEvC;;;;;GAKG;AACH,MAAqB,YAAY;IAAjC;QACU,YAAO,GAAW,EAAE,CAAA;QACpB,cAAS,GAAW,CAAC,CAAA;IAuB/B,CAAC;IArBC,8BAA8B;IACvB,KAAK;QACV,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;QACxC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QACpC,CAAC;IACH,CAAC;IAED,oFAAoF;IAC7E,MAAM;QACX,IAAI,WAAmB,CAAA;QACvB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACrD,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACtD,CAAC;aAAM,CAAC;YACN,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAA;YACvD,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,CAAC,CAAA;QACtD,CAAC;QAED,OAAO,IAAI,qBAAW,CAAC,WAAW,CAAC,CAAA;IACrC,CAAC;CACF;AAzBD,+BAyBC"}
1
+ {"version":3,"file":"TimeMeasurer.js","sourceRoot":"","sources":["../src/TimeMeasurer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,MAAM,OAAO,YAAY;IACf,OAAO,GAAW,EAAE,CAAA;IACpB,SAAS,GAAW,CAAC,CAAA;IAE7B;;;OAGG;IACI,MAAM,CAAC,KAAK;QACjB,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAA;QACnC,QAAQ,CAAC,KAAK,EAAE,CAAA;QAChB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7C,CAAC;QAED,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;QACxC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QACpC,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,MAAM;QACX,IAAI,WAAmB,CAAA;QACvB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACrD,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACtD,CAAC;aAAM,CAAC;YACN,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAA;YACvD,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,CAAC,CAAA;QACtD,CAAC;QAED,OAAO,IAAI,WAAW,CAAC,WAAW,CAAC,CAAA;IACrC,CAAC;CACF"}