Skip to content

Commit

Permalink
Merge pull request #7421 from holomorfo/bench
Browse files Browse the repository at this point in the history
[dev-2.0] Benchmark setup and sample report for render and batch
  • Loading branch information
limzykenneth authored Dec 17, 2024
2 parents b89ac5b + 371c2c7 commit 532e780
Show file tree
Hide file tree
Showing 6 changed files with 541 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"dev": "vite preview/",
"dev:global": "concurrently -n build,server \"rollup -c -w\" \"npx vite preview/global/\"",
"docs": "documentation build ./src/**/*.js ./src/**/**/*.js -o ./docs/data.json && node ./utils/convert.js",
"bench": "vitest bench",
"bench:report": "vitest bench --reporter=verbose",
"test": "vitest",
"lint": "eslint .",
"lint:fix": "eslint --fix ."
Expand Down
134 changes: 134 additions & 0 deletions test/bench/REPORTS/REPORT_1_TEST CPU.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Benchmark Report

## Sample Test Results

This benchmark report summarizes the performance of tests on the `test/bench/cpu_transforms.ench.js` script, comparing CPU transforms set to true and false. The results show that TEST CPU TRANSFORMS false consistently outperforms true, with higher operations per second (ops/sec) and lower statistical variations. For example, in one test, false achieved 0.9418 ops/sec compared to true at 0.7533 ops/sec, making false 1.25x faster. The report includes detailed metrics and a summary of the relative performance differences.

https://editor.p5js.org/davepagurek/sketches/FAqbP5k8i

## Script that we are benchmarking

Since in the test environment we are not running the draw function we are benchmarking the first run of the draw.

```
const TEST_CPU_TRANSFORMS = false
// Not testing strokes rn because they're slower in general and we don't
// need them for this test to make sense
p5.Geometry.prototype._edgesToVertices = () => {}
let fps
const state = []
function setup() {
createCanvas(400, 400, WEBGL);
for (let i = 0; i < 100; i++) {
state.push({
pos: createVector(random(-200, 200), random(-200, 200)),
vel: createVector(random(-2, 2), random(-2, 2)),
})
}
fps = createP()
}
function draw() {
background(220);
for (const s of state) {
s.pos.add(s.vel)
for (const axis of ['x', 'y']) {
if (s.pos[axis] < -200) {
s.pos[axis] = -200
s.vel[axis] *= -1
}
if (s.pos[axis] > 200) {
s.pos[axis] = 200
s.vel[axis] *= -1
}
}
}
const drawCircles = () => {
for (const s of state) {
push()
translate(s.pos.x, s.pos.y)
const pts = 500
beginShape(TRIANGLE_FAN)
vertex(0,0)
for (let i = 0; i <= pts; i++) {
const a = (i/pts) * TWO_PI
vertex(5*cos(a), 5*sin(a))
}
endShape()
pop()
}
}
if (TEST_CPU_TRANSFORMS) {
// Flattens into a single buffer
const shape = buildGeometry(drawCircles)
model(shape)
freeGeometry(model)
} else {
drawCircles()
}
fps.html(round(frameRate()))
}
```


### test/bench/dave.bench.js (2) 35272ms
- **Dave bench test (2) 35268ms**
- **TEST CPU TRANSFORMS true**: 0.7533 ops/sec ±3.80% (10 samples)
- **TEST CPU TRANSFORMS false**: 0.9418 ops/sec ±0.20% (10 samples) _fastest_

#### Summary
- **TEST CPU TRANSFORMS false** is 1.25x faster than **TEST CPU TRANSFORMS true**

### Separated
#### test/bench/dave.bench.js (2) 27912ms
- **Dave bench test (2) 27909ms**
- **TEST CPU TRANSFORMS false**: 0.5350 ops/sec ±4.39% (10 samples)
- **TEST CPU TRANSFORMS true**: _skipped_

#### test/bench/dave.bench.js (2) 19331ms
- **Dave bench test (2) 19327ms**
- **TEST CPU TRANSFORMS false**: _skipped_
- **TEST CPU TRANSFORMS true**: 0.7519 ops/sec ±3.80% (10 samples)

### Comparing
#### DEV v2.1.5 /Users/cristianbanuelos/repos/p5.js.git/bench
- **test/bench/dave.bench.js (2) 15671ms**
- **Dave bench test (2) 15667ms**
- **TEST CPU TRANSFORMS false**: 0.9719 ops/sec ±1.36% (2 samples) _fastest_
- **TEST CPU TRANSFORMS true**: 0.8170 ops/sec ±15.16% (2 samples)

#### Summary
- **TEST CPU TRANSFORMS false** is 1.19x faster than **TEST CPU TRANSFORMS true**

#### DEV v2.1.5 /Users/cristianbanuelos/repos/p5.js.git/bench
- **test/bench/dave.bench.js (2) 15915ms**
- **Dave bench test (2) 15905ms**
- **TEST CPU TRANSFORMS true**: 0.7961 ops/sec ±4.86% (2 samples)
- **TEST CPU TRANSFORMS false**: 0.9286 ops/sec ±36.88% (2 samples) _fastest_

#### Summary
- **TEST CPU TRANSFORMS false** is 1.17x faster than **TEST CPU TRANSFORMS true**

## With 1000 Elements
### test/bench/dave.bench.js (2) 151509ms
- **Dave bench test (2) 151505ms**
- **TEST CPU TRANSFORMS true**: 0.0582 ops/sec ±0.00% (1 sample)
- **TEST CPU TRANSFORMS false**: 0.0912 ops/sec ±0.00% (1 sample) _fastest_

#### Summary
- **TEST CPU TRANSFORMS false** is 1.57x faster than **TEST CPU TRANSFORMS true**

### 1000 Elements Second Run
#### test/bench/dave.bench.js (2) 150601ms
- **Dave bench test (2) 150597ms**
- **TEST CPU TRANSFORMS true**: 0.0589 ops/sec ±0.00% (1 sample)
- **TEST CPU TRANSFORMS false**: 0.0914 ops/sec ±0.00% (1 sample) _fastest_

#### Summary
- **TEST CPU TRANSFORMS false** is 1.55x faster than **TEST CPU TRANSFORMS true**
168 changes: 168 additions & 0 deletions test/bench/cpu_transforms.bench.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// import p5 from "../../../src/app.js";
import { bench, describe } from "vitest";
import p5 from "../../src/app";

const options = { iterations: 1, time: 1500 };
const ITERATIONS = 100
describe.sequential("Dave bench test", () => {
bench(
"TEST CPU TRANSFORMS true",
async () => {
try {
const TEST_CPU_TRANSFORMS = true;
var myp5;
new p5(function (p) {
p.setup = function () {
myp5 = p;
};
});
await vi.waitFor(() => {
if (myp5 === undefined) {
throw new Error("not ready");
}
});
let fps;
const state = [];

myp5.createCanvas(400, 400, myp5.WEBGL);
for (let i = 0; i < ITERATIONS; i++) {
state.push({
pos: myp5.createVector(
myp5.random(-200, 200),
myp5.random(-200, 200)
),
vel: myp5.createVector(myp5.random(-2, 2), myp5.random(-2, 2)),
});
}
fps = myp5.createP();

assert.equal(myp5.webglVersion, myp5.webglVersion);
myp5.remove();

// Now what's in draw
myp5.background(220);

for (const s of state) {
s.pos.add(s.vel);
for (const axis of ["x", "y"]) {
if (s.pos[axis] < -200) {
s.pos[axis] = -200;
s.vel[axis] *= -1;
}
if (s.pos[axis] > 200) {
s.pos[axis] = 200;
s.vel[axis] *= -1;
}
}
}

const drawCircles = () => {
for (const s of state) {
myp5.push();
myp5.translate(s.pos.x, s.pos.y);
const pts = 500;
myp5.beginShape(myp5.TRIANGLE_FAN);
myp5.vertex(0, 0);
for (let i = 0; i <= pts; i++) {
const a = (i / pts) * myp5.TWO_PI;
myp5.vertex(5 * myp5.cos(a), 5 * myp5.sin(a));
}
myp5.endShape();
myp5.pop();
}
};

if (TEST_CPU_TRANSFORMS) {
// Flattens into a single buffer
const shape = myp5.buildGeometry(drawCircles);
myp5.model(shape);
myp5.freeGeometry(myp5.model);
} else {
drawCircles();
}
} catch (error) {
console.log(error);
}
},
options
),
options;
bench(
"TEST CPU TRANSFORMS false",
async () => {
const TEST_CPU_TRANSFORMS = false;
var myp5;
new p5(function (p) {
p.setup = function () {
myp5 = p;
};
});
await vi.waitFor(() => {
if (myp5 === undefined) {
throw new Error("not ready");
}
});
let fps;
const state = [];

myp5.createCanvas(400, 400, myp5.WEBGL);
for (let i = 0; i < ITERATIONS; i++) {
state.push({
pos: myp5.createVector(
myp5.random(-200, 200),
myp5.random(-200, 200)
),
vel: myp5.createVector(myp5.random(-2, 2), myp5.random(-2, 2)),
});
}
fps = myp5.createP();

assert.equal(myp5.webglVersion, myp5.webglVersion);
myp5.remove();

// Now what's in draw
myp5.background(220);

for (const s of state) {
s.pos.add(s.vel);
for (const axis of ["x", "y"]) {
if (s.pos[axis] < -200) {
s.pos[axis] = -200;
s.vel[axis] *= -1;
}
if (s.pos[axis] > 200) {
s.pos[axis] = 200;
s.vel[axis] *= -1;
}
}
}

const drawCircles = () => {
for (const s of state) {
myp5.push();
myp5.translate(s.pos.x, s.pos.y);
const pts = 500;
myp5.beginShape(myp5.TRIANGLE_FAN);
myp5.vertex(0, 0);
for (let i = 0; i <= pts; i++) {
const a = (i / pts) * myp5.TWO_PI;
myp5.vertex(5 * myp5.cos(a), 5 * myp5.sin(a));
}
myp5.endShape();
myp5.pop();
}
};

if (TEST_CPU_TRANSFORMS) {
// Flattens into a single buffer
const shape = myp5.buildGeometry(drawCircles);
myp5.model(shape);
myp5.freeGeometry(myp5.model);
} else {
drawCircles();
}
},
options
),
options;
});
29 changes: 29 additions & 0 deletions test/bench/poc.bench.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { bench, describe } from "vitest";

describe.only("sort", () => {
bench(
"normal",
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
throw new Error("error");
},
{ iterations: 100 }
);

bench(
"reverse",
() => {
const x = [1, 5, 4, 2, 3];
x.reverse()
.reverse()
.reverse()
.sort((a, b) => {
return a - b;
});
},
{ iterations: 10 }
);
});
Loading

0 comments on commit 532e780

Please sign in to comment.