Skip to content

Commit 77fc362

Browse files
authored
Add shimmer benchmarks (#5597)
1 parent 95f7476 commit 77fc362

File tree

9 files changed

+374
-2
lines changed

9 files changed

+374
-2
lines changed

.gitlab/benchmarks.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,26 @@ benchmark:
6565
GROUP: 2
6666
- MAJOR_VERSION: 18
6767
GROUP: 3
68+
- MAJOR_VERSION: 18
69+
GROUP: 4
6870
- MAJOR_VERSION: 20
6971
GROUP: 1
7072
- MAJOR_VERSION: 20
7173
GROUP: 2
7274
- MAJOR_VERSION: 20
7375
GROUP: 3
76+
- MAJOR_VERSION: 20
77+
GROUP: 4
7478
- MAJOR_VERSION: 22
7579
GROUP: 1
7680
- MAJOR_VERSION: 22
7781
GROUP: 2
7882
- MAJOR_VERSION: 22
7983
GROUP: 3
84+
- MAJOR_VERSION: 22
85+
GROUP: 4
8086
variables:
81-
SPLITS: 3
87+
SPLITS: 4
8288

8389
benchmark-serverless:
8490
stage: benchmarks

benchmark/sirun/README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,29 @@
22

33
This directory contains several different types of benchmarks.
44

5-
Some of these benchmarks rely on [sirun](https://github.com/DataDog/sirun/) for execution.
5+
These benchmarks rely on [sirun](https://github.com/DataDog/sirun/) for execution.
6+
7+
## Running Benchmarks Locally
8+
9+
First, install sirun:
10+
11+
```sh
12+
cargo install --git https://github.com/DataDog/sirun.git --branch main
13+
```
14+
15+
Then, get into one of the directories alongside this file, and run the following:
16+
17+
```sh
18+
node ../run-all-variants.js
19+
```
20+
21+
You can pipe this to `sirun --summarize` to get a summary of the resulting data. This can also be piped to the `means.js` script in this directory to view it in tabular form.
22+
23+
Putting that all together, the following will run benchmarks, summarize them, and give you nice tabular output.
24+
25+
```sh
26+
node ../run-all-variants.js | sirun --summarize | node ../means.js
27+
```
628

729
## Running Benchmarks via Docker
830

benchmark/sirun/means.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* eslint-disable no-console */
2+
3+
const chunks = []
4+
process.stdin.on('data', (data) => {
5+
chunks.push(data)
6+
})
7+
process.stdin.on('end', () => {
8+
const data = Buffer.concat(chunks).toString()
9+
const json = JSON.parse(data)
10+
for (const testSuite in json) {
11+
console.log('Test Suite: ', testSuite)
12+
const variants = Object.keys(json[testSuite])
13+
const results = {}
14+
for (const variant of variants) {
15+
const { summary } = json[testSuite][variant]
16+
results[variant] = {
17+
wallTime: summary['wall.time'].mean,
18+
userTime: summary['user.time'].mean,
19+
sysTime: summary['system.time'].mean,
20+
maxResSize: summary['max.res.size'].mean
21+
}
22+
}
23+
const newResults = []
24+
Object.keys(results).sort().forEach((name) => {
25+
newResults.push({ name, ...results[name] })
26+
})
27+
console.table(newResults)
28+
}
29+
})
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This is a test of shimmer performance at startup, meaning the actual shimming operations of shimmer.wrap and shimmer.wrapFunction.
2+
3+
There are variants for different kinds of functions, and for both types of shimming.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-disable require-await */
2+
3+
const shimmer = require('../../../packages/datadog-shimmer')
4+
5+
const {
6+
ENABLED,
7+
WRAP_FUNCTION,
8+
FUNCTION_NAME
9+
} = process.env
10+
11+
const ITERATIONS = 2e6
12+
13+
let counter = 0
14+
function declared () {
15+
return ++counter // Do very little
16+
}
17+
18+
const arrow = () => {
19+
return ++counter // Do very little
20+
}
21+
22+
async function asyncDeclared () {
23+
return ++counter // Do very little
24+
}
25+
26+
const asyncArrow = async () => {
27+
return ++counter // Do very little
28+
}
29+
30+
const testedFn = {
31+
declared,
32+
arrow,
33+
asyncDeclared,
34+
asyncArrow
35+
}[FUNCTION_NAME]
36+
if (!testedFn) {
37+
throw new Error(`Function ${FUNCTION_NAME} not found`)
38+
}
39+
40+
if (ENABLED !== 'true') {
41+
for (let i = 0; i < ITERATIONS; i++) {
42+
testedFn()
43+
}
44+
} else {
45+
if (WRAP_FUNCTION === 'true') {
46+
const wrapped = shimmer.wrapFunction(testedFn, (original) => {
47+
return function () {
48+
return original.apply(this, arguments)
49+
}
50+
})
51+
for (let i = 0; i < ITERATIONS; i++) {
52+
wrapped()
53+
}
54+
} else {
55+
const obj = {
56+
testedFn
57+
}
58+
shimmer.wrap(obj, 'testedFn', (original) => {
59+
return function () {
60+
return original.apply(this, arguments)
61+
}
62+
})
63+
const wrapped = obj.testedFn
64+
for (let i = 0; i < ITERATIONS; i++) {
65+
wrapped()
66+
}
67+
}
68+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{
2+
"name": "shimmer-runtime",
3+
"run": "node index.js",
4+
"run_with_affinity": "bash -c \"taskset -c $CPU_AFFINITY node index.js\"",
5+
"cachegrind": false,
6+
"iterations": 10,
7+
"instructions": true,
8+
"variants": {
9+
"declared-baseline": {
10+
"env": {
11+
"ENABLED": "false",
12+
"FUNCTION_NAME": "declared"
13+
}
14+
},
15+
"asyncdeclared-baseline": {
16+
"env": {
17+
"ENABLED": "false",
18+
"FUNCTION_NAME": "asyncDeclared"
19+
}
20+
},
21+
"arrow-baseline": {
22+
"env": {
23+
"ENABLED": "false",
24+
"FUNCTION_NAME": "arrow"
25+
}
26+
},
27+
"asyncarrow-baseline": {
28+
"env": {
29+
"ENABLED": "false",
30+
"FUNCTION_NAME": "asyncArrow"
31+
}
32+
},
33+
"declared-wrapfn": {
34+
"env": {
35+
"ENABLED": "true",
36+
"WRAP_FUNCTION": "true",
37+
"FUNCTION_NAME": "declared"
38+
}
39+
},
40+
"asyncdeclared-wrapfn": {
41+
"env": {
42+
"ENABLED": "true",
43+
"WRAP_FUNCTION": "true",
44+
"FUNCTION_NAME": "asyncDeclared"
45+
}
46+
},
47+
"arrow-wrapfn": {
48+
"env": {
49+
"ENABLED": "true",
50+
"WRAP_FUNCTION": "true",
51+
"FUNCTION_NAME": "arrow"
52+
}
53+
},
54+
"asyncarrow-wrapfn": {
55+
"env": {
56+
"ENABLED": "true",
57+
"WRAP_FUNCTION": "true",
58+
"FUNCTION_NAME": "asyncArrow"
59+
}
60+
},
61+
"declared-wrap": {
62+
"env": {
63+
"ENABLED": "true",
64+
"WRAP_FUNCTION": "false",
65+
"FUNCTION_NAME": "declared"
66+
}
67+
},
68+
"asyncdeclared-wrap": {
69+
"env": {
70+
"ENABLED": "true",
71+
"WRAP_FUNCTION": "false",
72+
"FUNCTION_NAME": "asyncDeclared"
73+
}
74+
},
75+
"arrow-wrap": {
76+
"env": {
77+
"ENABLED": "true",
78+
"WRAP_FUNCTION": "false",
79+
"FUNCTION_NAME": "arrow"
80+
}
81+
},
82+
"asyncarrow-wrap": {
83+
"env": {
84+
"ENABLED": "true",
85+
"WRAP_FUNCTION": "false",
86+
"FUNCTION_NAME": "asyncArrow"
87+
}
88+
}
89+
}
90+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This is a test of shimmer performance at runtime, meaning the performance of functions shimmed by shimmer.wrap and shimmer.wrapFunction.
2+
3+
There are variants for different kinds of functions, and for both types of shimming.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* eslint-disable require-await */
2+
3+
const shimmer = require('../../../packages/datadog-shimmer')
4+
5+
const {
6+
ENABLED,
7+
WRAP_FUNCTION,
8+
FUNCTION_NAME
9+
} = process.env
10+
11+
const ITERATIONS = 2e6
12+
13+
let counter = 0
14+
function declared () {
15+
return ++counter // Do very little
16+
}
17+
18+
const arrow = () => {
19+
return ++counter // Do very little
20+
}
21+
22+
async function asyncDeclared () {
23+
return ++counter // Do very little
24+
}
25+
26+
const asyncArrow = async () => {
27+
return ++counter // Do very little
28+
}
29+
30+
const testedFn = {
31+
declared,
32+
arrow,
33+
asyncDeclared,
34+
asyncArrow
35+
}[FUNCTION_NAME]
36+
if (!testedFn) {
37+
throw new Error(`Function ${FUNCTION_NAME} not found`)
38+
}
39+
40+
if (ENABLED === 'true') {
41+
if (WRAP_FUNCTION === 'true') {
42+
for (let i = 0; i < ITERATIONS; i++) {
43+
shimmer.wrapFunction(testedFn, (original) => {
44+
return function () {
45+
return original.apply(this, arguments)
46+
}
47+
})
48+
}
49+
} else {
50+
const obj = {
51+
testedFn
52+
}
53+
for (let i = 0; i < ITERATIONS; i++) {
54+
shimmer.wrap(obj, 'testedFn', (original) => {
55+
return function () {
56+
return original.apply(this, arguments)
57+
}
58+
})
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)