Skip to content

Commit 05c22ba

Browse files
committed
libuv-size
1 parent 9e3721c commit 05c22ba

File tree

3 files changed

+91
-21
lines changed

3 files changed

+91
-21
lines changed

packages/dd-trace/src/profiling/exporters/event_serializer.js

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,7 @@
55
const os = require('os')
66
const perf = require('perf_hooks').performance
77
const version = require('../../../../../package.json').version
8-
const { getEnvironmentVariable } = require('../../config-helper')
9-
10-
const libuvThreadPoolSize = (() => {
11-
const ss = getEnvironmentVariable('UV_THREADPOOL_SIZE')
12-
if (ss === undefined) {
13-
// Backend will apply the default size based on Node version.
14-
return
15-
}
16-
// libuv uses atoi to parse the value, which is almost the same as parseInt, except that parseInt
17-
// will return NaN on invalid input, while atoi will return 0. This is handled at return.
18-
const s = Number.parseInt(ss)
19-
// We don't interpret the value further here in the library. Backend will interpret the number
20-
// based on Node version. In all currently known Node versions, 0 results in 1 worker thread,
21-
// negative values (because they're assigned to an unsigned int) become very high positive values,
22-
// and the value is finally capped at 1024.
23-
return Number.isNaN(s) ? 0 : s
24-
})()
8+
const { availableParallelism, libuvThreadPoolSize } = require('../libuv-size')
259

2610
class EventSerializer {
2711
constructor ({ env, host, service, version, libraryInjected, activation } = {}) {
@@ -77,10 +61,7 @@ class EventSerializer {
7761
version
7862
},
7963
runtime: {
80-
// os.availableParallelism only available in node 18.14.0/19.4.0 and above
81-
available_processors: typeof os.availableParallelism === 'function'
82-
? os.availableParallelism()
83-
: os.cpus().length,
64+
available_processors: availableParallelism(),
8465
// Using `nodejs` for consistency with the existing `runtime` tag.
8566
// Note that the event `family` property uses `node`, as that's what's
8667
// proscribed by the Intake API, but that's an internal enum and is
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const { getEnvironmentVariable } = require('../config-helper')
2+
const os = require('node:os')
3+
4+
function getLibuvThreadPoolSize(envVar) {
5+
if (envVar === undefined) {
6+
return
7+
}
8+
// libuv uses atoi to parse the value, which is almost the same as parseInt, except that parseInt
9+
// will return NaN on invalid input, while atoi will return 0. This is handled at return.
10+
const s = Number.parseInt(envVar, 10)
11+
// We don't interpret the value further here in the library. Backend will interpret the number
12+
// based on Node version.
13+
return Number.isNaN(s) ? 0 : s
14+
}
15+
16+
const libuvThreadPoolSize = getLibuvThreadPoolSize(getEnvironmentVariable('UV_THREADPOOL_SIZE'))
17+
18+
function getEffectiveLibuvThreadCount(size) {
19+
// In all currently known Node versions, 0 results in 1 worker thread, negative values (because
20+
// they're assigned to an unsigned int) become very high positive values, and the value is finally
21+
// capped at 1024.
22+
if (size === undefined) {
23+
return 4
24+
} else if (size < 0 || size > 1024) {
25+
return 1024
26+
} else if (size === 0) {
27+
return 1
28+
} else {
29+
return size
30+
}
31+
}
32+
33+
const effectiveLibuvThreadCount = getEffectiveLibuvThreadCount(libuvThreadPoolSize)
34+
35+
function availableParallelism() {
36+
// os.availableParallelism only available in node 18.14.0/19.4.0 and above
37+
return typeof os.availableParallelism === 'function' ? os.availableParallelism() : os.cpus().length
38+
}
39+
40+
module.exports = {
41+
availableParallelism,
42+
effectiveLibuvThreadCount,
43+
libuvThreadPoolSize,
44+
// Only used for testing
45+
getLibuvThreadPoolSize,
46+
getEffectiveLibuvThreadCount
47+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict'
2+
3+
require('../setup/tap')
4+
5+
const { expect } = require('chai')
6+
const libuvSize = require('../../src/profiling/libuv-size')
7+
8+
describe('libuv-size', function () {
9+
describe('getLibuvThreadPoolSize should return', function () {
10+
it('undefined if no environment variable is set', function () {
11+
expect(libuvSize.getLibuvThreadPoolSize()).to.equal(undefined)
12+
})
13+
it('0 for an empty environment variable', function () {
14+
expect(libuvSize.getLibuvThreadPoolSize('')).to.equal(0)
15+
})
16+
it('0 for an invalid environment variable', function () {
17+
expect(libuvSize.getLibuvThreadPoolSize('invalid')).to.equal(0)
18+
})
19+
it('a parsed numeric value', function () {
20+
expect(libuvSize.getLibuvThreadPoolSize('100')).to.equal(100)
21+
})
22+
})
23+
describe('getEffectiveLibuvThreadPoolSize should return', function () {
24+
it('the libuv thread pool size if set', function () {
25+
expect(libuvSize.getEffectiveLibuvThreadCount(100)).to.equal(100)
26+
})
27+
it('the default value if not set', function () {
28+
expect(libuvSize.getEffectiveLibuvThreadCount()).to.equal(4)
29+
})
30+
it('1 if set to 0', function () {
31+
expect(libuvSize.getEffectiveLibuvThreadCount(0)).to.equal(1)
32+
})
33+
it('1024 if set to a negative value', function () {
34+
expect(libuvSize.getEffectiveLibuvThreadCount(-1)).to.equal(1024)
35+
expect(libuvSize.getEffectiveLibuvThreadCount(-100000)).to.equal(1024)
36+
})
37+
it('1024 if set to a very large value', function () {
38+
expect(libuvSize.getEffectiveLibuvThreadCount(1025)).to.equal(1024)
39+
expect(libuvSize.getEffectiveLibuvThreadCount(100000)).to.equal(1024)
40+
})
41+
})
42+
})

0 commit comments

Comments
 (0)