Skip to content

Commit 873b32a

Browse files
committed
add continuous benchmarking powered by CodSpeed
1 parent d251b58 commit 873b32a

File tree

10 files changed

+605
-18
lines changed

10 files changed

+605
-18
lines changed

.github/workflows/codspeed.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: CodSpeed
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
workflow_dispatch:
9+
10+
jobs:
11+
codspeed:
12+
strategy:
13+
fail-fast: true
14+
matrix:
15+
test-file:
16+
- benchmarks/codspeed-primitive-encode.ts
17+
- benchmarks/codspeed-primitive-decode.ts
18+
- benchmarks/codspeed-complex-encode.ts
19+
- benchmarks/codspeed-complex-decode.ts
20+
name: Run CodSpeed benchmarks
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read # required for actions/checkout
24+
id-token: write # required for OIDC authentication with CodSpeed
25+
steps:
26+
- uses: actions/checkout@v6
27+
28+
- uses: actions/setup-node@v6
29+
with:
30+
node-version: 25
31+
cache: yarn
32+
33+
- name: Install Dependencies
34+
run: yarn install --immutable
35+
36+
- name: Run benchmarks
37+
uses: CodSpeedHQ/action@v4
38+
with:
39+
mode: simulation
40+
run: node ${{ matrix.test-file }}

benchmarks/_specs.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { create } from 'domain';
21
import * as r from 'rkyv-js';
32

43
interface Spec<T = unknown> {
@@ -59,7 +58,7 @@ export const specs: Spec[] = [
5958
followingCount: r.u32,
6059
}),
6160
[
62-
['Simple user profile', {
61+
['User profile', {
6362
id: 12345678901234n,
6463
username: 'johndoe',
6564
email: 'john.doe@example.com',
@@ -171,15 +170,15 @@ export const specs: Spec[] = [
171170
NotFound: r.unit,
172171
}),
173172
[
174-
['Success', {
173+
['ApiResponse::Success', {
175174
tag: 'Success',
176175
value: { data: '{"users": [1, 2, 3]}', timestamp: 1704067200000n },
177176
}],
178-
['Error', {
177+
['ApiResponse::Error', {
179178
tag: 'Error',
180179
value: { code: 404, message: 'Resource not found' },
181180
}],
182-
['Loading', {
181+
['ApiResponse::Loading', {
183182
tag: 'Loading',
184183
value: null,
185184
}],
@@ -195,9 +194,9 @@ export const specs: Spec[] = [
195194
Point: r.unit,
196195
}),
197196
[
198-
['Circle', { tag: 'Circle', value: { radius: 5.0 } }],
199-
['Rectangle', { tag: 'Rectangle', value: { width: 10.0, height: 20.0 } }],
200-
['Point', { tag: 'Point', value: null }],
197+
['Shape::Circle', { tag: 'Circle', value: { radius: 5.0 } }],
198+
['Shape::Rectangle', { tag: 'Rectangle', value: { width: 10.0, height: 20.0 } }],
199+
['Shape::Point', { tag: 'Point', value: null }],
201200
],
202201
),
203202

@@ -227,11 +226,11 @@ export const specs: Spec[] = [
227226
Deleted: r.unit,
228227
}),
229228
[
230-
['Text', {
229+
['Message::Text', {
231230
tag: 'Text',
232231
value: { content: 'Hello, world! How are you doing today?', edited: false },
233232
}],
234-
['Image', {
233+
['Message::Image', {
235234
tag: 'Image',
236235
value: {
237236
url: 'https://example.com/images/photo-12345.jpg',
@@ -240,7 +239,7 @@ export const specs: Spec[] = [
240239
caption: 'Beautiful sunset at the beach',
241240
},
242241
}],
243-
['File', {
242+
['Message::File', {
244243
tag: 'File',
245244
value: {
246245
url: 'https://example.com/files/document.pdf',
@@ -283,15 +282,15 @@ export const specs: Spec[] = [
283282
}),
284283
}),
285284
[
286-
['UserCreated', {
285+
['Event::UserCreated', {
287286
tag: 'UserCreated',
288287
value: {
289288
userId: 12345n,
290289
username: 'newuser',
291290
email: 'newuser@example.com',
292291
},
293292
}],
294-
['OrderPlaced', {
293+
['Event::OrderPlaced', {
295294
tag: 'OrderPlaced',
296295
value: {
297296
orderId: 9001n,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Bench } from 'tinybench';
2+
import { withCodSpeed } from '@codspeed/tinybench-plugin';
3+
import * as r from 'rkyv-js';
4+
5+
import { specs } from './_specs.ts';
6+
7+
const bench = withCodSpeed(new Bench());
8+
9+
for (const spec of specs) {
10+
for (const [description, test] of spec.tests) {
11+
bench.add(`complex/decode - ${description}`, () => {
12+
r.decode(spec.codec, test.expected);
13+
});
14+
}
15+
}
16+
17+
await bench.run();
18+
console.table(bench.table());
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Bench } from 'tinybench';
2+
import { withCodSpeed } from '@codspeed/tinybench-plugin';
3+
import * as r from 'rkyv-js';
4+
5+
import { specs } from './_specs.ts';
6+
7+
const bench = withCodSpeed(new Bench());
8+
9+
for (const spec of specs) {
10+
for (const [description, test] of spec.tests) {
11+
bench.add(`complex/encode - ${description}`, () => {
12+
r.encode(spec.codec, test.input);
13+
});
14+
}
15+
}
16+
17+
await bench.run();
18+
console.table(bench.table());
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { Bench } from 'tinybench';
2+
import { withCodSpeed } from '@codspeed/tinybench-plugin';
3+
import * as r from 'rkyv-js';
4+
5+
const bench = withCodSpeed(new Bench());
6+
7+
const testU8 = 255;
8+
const testI8 = -128;
9+
const testU16 = 65535;
10+
const testI16 = -32768;
11+
const testU32 = 4294967295;
12+
const testI32 = -2147483648;
13+
const testU64 = 18446744073709551615n;
14+
const testI64 = -9223372036854775808n;
15+
const testF32 = 3.14159;
16+
const testF64 = 3.141592653589793;
17+
const testBool = true;
18+
const testChar = '🦀';
19+
const testStringShort = 'Hello';
20+
const testStringLong = 'Hello, World! This is a longer string that exceeds inline storage.';
21+
22+
const u8Bytes = r.encode(r.u8, testU8);
23+
const i8Bytes = r.encode(r.i8, testI8);
24+
const u16Bytes = r.encode(r.u16, testU16);
25+
const i16Bytes = r.encode(r.i16, testI16);
26+
const u32Bytes = r.encode(r.u32, testU32);
27+
const i32Bytes = r.encode(r.i32, testI32);
28+
const u64Bytes = r.encode(r.u64, testU64);
29+
const i64Bytes = r.encode(r.i64, testI64);
30+
const f32Bytes = r.encode(r.f32, testF32);
31+
const f64Bytes = r.encode(r.f64, testF64);
32+
const boolBytes = r.encode(r.bool, testBool);
33+
const charBytes = r.encode(r.char, testChar);
34+
const stringShortBytes = r.encode(r.string, testStringShort);
35+
const stringLongBytes = r.encode(r.string, testStringLong);
36+
37+
bench.add('primitives/decode - u8', () => {
38+
r.decode(r.u8, u8Bytes);
39+
});
40+
41+
bench.add('primitives/decode - i8', () => {
42+
r.decode(r.i8, i8Bytes);
43+
});
44+
45+
bench.add('primitives/decode - u16', () => {
46+
r.decode(r.u16, u16Bytes);
47+
});
48+
49+
bench.add('primitives/decode - i16', () => {
50+
r.decode(r.i16, i16Bytes);
51+
});
52+
53+
bench.add('primitives/decode - u32', () => {
54+
r.decode(r.u32, u32Bytes);
55+
});
56+
57+
bench.add('primitives/decode - i32', () => {
58+
r.decode(r.i32, i32Bytes);
59+
});
60+
61+
bench.add('primitives/decode - u64', () => {
62+
r.decode(r.u64, u64Bytes);
63+
});
64+
65+
bench.add('primitives/decode - i64', () => {
66+
r.decode(r.i64, i64Bytes);
67+
});
68+
69+
bench.add('primitives/decode - f32', () => {
70+
r.decode(r.f32, f32Bytes);
71+
});
72+
73+
bench.add('primitives/decode - f64', () => {
74+
r.decode(r.f64, f64Bytes);
75+
});
76+
77+
bench.add('primitives/decode - bool', () => {
78+
r.decode(r.bool, boolBytes);
79+
});
80+
81+
bench.add('primitives/decode - char', () => {
82+
r.decode(r.char, charBytes);
83+
});
84+
85+
bench.add('primitives/decode - string (short)', () => {
86+
r.decode(r.string, stringShortBytes);
87+
});
88+
89+
bench.add('primitives/decode - string (long)', () => {
90+
r.decode(r.string, stringLongBytes);
91+
});
92+
93+
await bench.run();
94+
console.table(bench.table());
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { Bench } from 'tinybench';
2+
import { withCodSpeed } from '@codspeed/tinybench-plugin';
3+
import * as r from 'rkyv-js';
4+
5+
const bench = withCodSpeed(new Bench());
6+
7+
const testU8 = 255;
8+
const testI8 = -128;
9+
const testU16 = 65535;
10+
const testI16 = -32768;
11+
const testU32 = 4294967295;
12+
const testI32 = -2147483648;
13+
const testU64 = 18446744073709551615n;
14+
const testI64 = -9223372036854775808n;
15+
const testF32 = 3.14159;
16+
const testF64 = 3.141592653589793;
17+
const testBool = true;
18+
const testChar = '🦀';
19+
const testStringShort = 'Hello';
20+
const testStringLong = 'Hello, World! This is a longer string that exceeds inline storage.';
21+
22+
bench.add('primitives/encode - u8', () => {
23+
r.encode(r.u8, testU8);
24+
});
25+
26+
bench.add('primitives/encode - i8', () => {
27+
r.encode(r.i8, testI8);
28+
});
29+
30+
bench.add('primitives/encode - u16', () => {
31+
r.encode(r.u16, testU16);
32+
});
33+
34+
bench.add('primitives/encode - i16', () => {
35+
r.encode(r.i16, testI16);
36+
});
37+
38+
bench.add('primitives/encode - u32', () => {
39+
r.encode(r.u32, testU32);
40+
});
41+
42+
bench.add('primitives/encode - i32', () => {
43+
r.encode(r.i32, testI32);
44+
});
45+
46+
bench.add('primitives/encode - u64', () => {
47+
r.encode(r.u64, testU64);
48+
});
49+
50+
bench.add('primitives/encode - i64', () => {
51+
r.encode(r.i64, testI64);
52+
});
53+
54+
bench.add('primitives/encode - f32', () => {
55+
r.encode(r.f32, testF32);
56+
});
57+
58+
bench.add('primitives/encode - f64', () => {
59+
r.encode(r.f64, testF64);
60+
});
61+
62+
bench.add('primitives/encode - bool', () => {
63+
r.encode(r.bool, testBool);
64+
});
65+
66+
bench.add('primitives/encode - char', () => {
67+
r.encode(r.char, testChar);
68+
});
69+
70+
bench.add('primitives/encode - string (short)', () => {
71+
r.encode(r.string, testStringShort);
72+
});
73+
74+
bench.add('primitives/encode - string (long)', () => {
75+
r.encode(r.string, testStringLong);
76+
});
77+
78+
await bench.run();
79+
console.table(bench.table());

benchmarks/decode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { specs } from './_specs.ts';
55

66
for (const spec of specs) {
77
for (const [description, test] of spec.tests) {
8-
bench(`${spec.description} - ${description}`, () => {
8+
bench(`codec/decode - ${description}`, () => {
99
r.decode(spec.codec, test.expected);
1010
}).gc('inner');
1111
}

benchmarks/encode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { run, bench, group, summary } from 'mitata';
1+
import { run, bench } from 'mitata';
22
import * as r from 'rkyv-js';
33

44
import { specs } from './_specs.ts';
55

66
for (const spec of specs) {
77
for (const [description, test] of spec.tests) {
8-
bench(`${spec.description} - ${description}`, () => {
8+
bench(`codec/encode - ${description}`, () => {
99
r.encode(spec.codec, test.input);
1010
}).gc('inner');
1111
}

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,18 @@
7070
"test": "node --test",
7171
"fixtures": "cargo run --bin generate-fixtures",
7272
"bench:comparison": "node --expose-gc benchmarks/comparison.ts",
73-
"bench:codec:primitives": "node --expose-gc benchmarks/codec-primitives.ts",
74-
"bench:codec:complex": "node --expose-gc benchmarks/codec-complex.ts"
73+
"bench:primitives": "node --expose-gc benchmarks/primitives.ts",
74+
"bench:encode": "node --expose-gc benchmarks/encode.ts",
75+
"bench:decode": "node --expose-gc benchmarks/decode.ts"
7576
},
7677
"devDependencies": {
78+
"@codspeed/tinybench-plugin": "^5.1.0",
7779
"@types/node": "^22.0.0",
7880
"capnp-es": "^0.0.14",
7981
"cbor-x": "^1.6.0",
8082
"mitata": "^1.0.34",
8183
"protobufjs": "^8.0.0",
84+
"tinybench": "^5.1.0",
8285
"typescript": "^5.9.3"
8386
}
8487
}

0 commit comments

Comments
 (0)