1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

perf(ext/web): optimize performance.measure() (#25774)

This PR optimizes the case when `performance.measure()` needs to find
the startMark by name. It is a simple change on `findMostRecent` fn to
avoiding copying and reversing the complete entries list.

Adds minor missing tests for:
- `clearMarks()`, general
- `clearMeasures()`, general
- `measure()`, case when the startMarks name exists more than once

### Benchmarks

#### main

```
    CPU | AMD Ryzen 7 PRO 6850U with Radeon Graphics
Runtime | Deno 2.0.0-rc.4 (x86_64-unknown-linux-gnu)

benchmark              time/iter (avg)        iter/s      (min … max)           p75      p99     p995
---------------------- ----------------------------- --------------------- --------------------------
worst case measure()            2.1 ms         486.9 (  1.7 ms …   2.4 ms)   2.2 ms   2.4 ms   2.4 ms
```

#### this PR

```
    CPU | AMD Ryzen 7 PRO 6850U with Radeon Graphics
Runtime | Deno 2.0.0-rc.4 (x86_64-unknown-linux-gnu)

benchmark              time/iter (avg)        iter/s      (min … max)           p75      p99     p995
---------------------- ----------------------------- --------------------- --------------------------
worst case measure()          966.3 µs         1,035 (876.9 µs …   1.1 ms)   1.0 ms   1.1 ms   1.1 ms
```

```ts
Deno.bench("worst case measure()", (b) => {
  performance.mark('start');

  for (let i = 0; i < 1e5; i += 1) {
    performance.mark(crypto.randomUUID());
  }

  b.start();

  performance.measure('total', 'start');

  b.end();

  performance.clearMarks();
  performance.clearMeasures();
});
```
This commit is contained in:
carles escrig royo 2024-09-21 01:24:59 +02:00 committed by GitHub
parent 55c22ee1bd
commit 88a469e823
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 7 deletions

View file

@ -3,10 +3,7 @@
import { primordials } from "ext:core/mod.js"; import { primordials } from "ext:core/mod.js";
const { const {
ArrayPrototypeFilter, ArrayPrototypeFilter,
ArrayPrototypeFind,
ArrayPrototypePush, ArrayPrototypePush,
ArrayPrototypeReverse,
ArrayPrototypeSlice,
ObjectKeys, ObjectKeys,
ObjectPrototypeIsPrototypeOf, ObjectPrototypeIsPrototypeOf,
ReflectHas, ReflectHas,
@ -101,10 +98,12 @@ function findMostRecent(
name, name,
type, type,
) { ) {
return ArrayPrototypeFind( for (let i = performanceEntries.length - 1; i >= 0; --i) {
ArrayPrototypeReverse(ArrayPrototypeSlice(performanceEntries)), const entry = performanceEntries[i];
(entry) => entry.name === name && entry.entryType === type, if (entry.name === name && entry.entryType === type) {
); return entry;
}
}
} }
function convertMarkToTimestamp(mark) { function convertMarkToTimestamp(mark) {

View file

@ -2,6 +2,7 @@
import { import {
assert, assert,
assertEquals, assertEquals,
assertNotEquals,
assertNotStrictEquals, assertNotStrictEquals,
assertStringIncludes, assertStringIncludes,
assertThrows, assertThrows,
@ -36,6 +37,41 @@ Deno.test(function performanceToJSON() {
assertEquals(Object.keys(json).length, 1); assertEquals(Object.keys(json).length, 1);
}); });
Deno.test(function clearMarks() {
performance.mark("a");
performance.mark("a");
performance.mark("b");
performance.mark("c");
const marksNum = performance.getEntriesByType("mark").length;
performance.clearMarks("a");
assertEquals(performance.getEntriesByType("mark").length, marksNum - 2);
performance.clearMarks();
assertEquals(performance.getEntriesByType("mark").length, 0);
});
Deno.test(function clearMeasures() {
performance.measure("from-start");
performance.mark("a");
performance.measure("from-mark-a", "a");
performance.measure("from-start");
performance.measure("from-mark-a", "a");
performance.mark("b");
performance.measure("between-a-and-b", "a", "b");
const measuresNum = performance.getEntriesByType("measure").length;
performance.clearMeasures("from-start");
assertEquals(performance.getEntriesByType("measure").length, measuresNum - 2);
performance.clearMeasures();
assertEquals(performance.getEntriesByType("measure").length, 0);
performance.clearMarks();
});
Deno.test(function performanceMark() { Deno.test(function performanceMark() {
const mark = performance.mark("test"); const mark = performance.mark("test");
assert(mark instanceof PerformanceMark); assert(mark instanceof PerformanceMark);
@ -127,6 +163,25 @@ Deno.test(function performanceMeasure() {
}); });
}); });
Deno.test(function performanceMeasureUseMostRecentMark() {
const markName1 = "mark1";
const measureName1 = "measure1";
const mark1 = performance.mark(markName1);
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
const laterMark1 = performance.mark(markName1);
const measure1 = performance.measure(measureName1, markName1);
assertNotEquals(mark1.startTime, measure1.startTime);
assertEquals(laterMark1.startTime, measure1.startTime);
} catch (e) {
return reject(e);
}
resolve();
}, 100);
});
});
Deno.test(function performanceCustomInspectFunction() { Deno.test(function performanceCustomInspectFunction() {
assertStringIncludes(Deno.inspect(performance), "Performance"); assertStringIncludes(Deno.inspect(performance), "Performance");
assertStringIncludes( assertStringIncludes(