Skip to content

Commit 7cf7dfb

Browse files
committed
libuv-size
1 parent 9e3721c commit 7cf7dfb

File tree

3 files changed

+101
-21
lines changed

3 files changed

+101
-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: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'use strict'
2+
3+
const { getEnvironmentVariable } = require('../config-helper')
4+
const os = require('node:os')
5+
6+
function getLibuvThreadPoolSize (envVar) {
7+
if (envVar === undefined) {
8+
return
9+
}
10+
// libuv uses atoi to parse the value, which is almost the same as parseInt, except that parseInt
11+
// will return NaN on invalid input, while atoi will return 0. This is handled at return.
12+
const s = Number.parseInt(envVar, 10)
13+
// We don't interpret the value further here in the library. Backend will interpret the number
14+
// based on Node version.
15+
return Number.isNaN(s) ? 0 : s
16+
}
17+
18+
const libuvThreadPoolSize = getLibuvThreadPoolSize(getEnvironmentVariable('UV_THREADPOOL_SIZE'))
19+
20+
function getEffectiveLibuvThreadCount (size) {
21+
// In all currently known Node versions, 0 results in 1 worker thread, negative values (because
22+
// they're assigned to an unsigned int) become very high positive values, and the value is finally
23+
// capped at 1024.
24+
if (size === undefined) {
25+
return 4
26+
} else if (size < 0 || size > 1024) {
27+
return 1024
28+
} else if (size === 0) {
29+
return 1
30+
}
31+
return size
32+
}
33+
34+
const effectiveLibuvThreadCount = getEffectiveLibuvThreadCount(libuvThreadPoolSize)
35+
36+
function availableParallelism () {
37+
// os.availableParallelism only available in node 18.14.0/19.4.0 and above
38+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
39+
return typeof os.availableParallelism === 'function' ? os.availableParallelism() : os.cpus().length
40+
}
41+
42+
module.exports = {
43+
availableParallelism,
44+
effectiveLibuvThreadCount,
45+
libuvThreadPoolSize,
46+
// Only used for testing
47+
getLibuvThreadPoolSize,
48+
getEffectiveLibuvThreadCount
49+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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+
14+
it('0 for an empty environment variable', function () {
15+
expect(libuvSize.getLibuvThreadPoolSize('')).to.equal(0)
16+
})
17+
18+
it('0 for an invalid environment variable', function () {
19+
expect(libuvSize.getLibuvThreadPoolSize('invalid')).to.equal(0)
20+
})
21+
22+
it('a parsed numeric value', function () {
23+
expect(libuvSize.getLibuvThreadPoolSize('100')).to.equal(100)
24+
})
25+
})
26+
27+
describe('getEffectiveLibuvThreadPoolSize should return', function () {
28+
it('the libuv thread pool size if set', function () {
29+
expect(libuvSize.getEffectiveLibuvThreadCount(100)).to.equal(100)
30+
})
31+
32+
it('the default value if not set', function () {
33+
expect(libuvSize.getEffectiveLibuvThreadCount()).to.equal(4)
34+
})
35+
36+
it('1 if set to 0', function () {
37+
expect(libuvSize.getEffectiveLibuvThreadCount(0)).to.equal(1)
38+
})
39+
40+
it('1024 if set to a negative value', function () {
41+
expect(libuvSize.getEffectiveLibuvThreadCount(-1)).to.equal(1024)
42+
expect(libuvSize.getEffectiveLibuvThreadCount(-100000)).to.equal(1024)
43+
})
44+
45+
it('1024 if set to a very large value', function () {
46+
expect(libuvSize.getEffectiveLibuvThreadCount(1025)).to.equal(1024)
47+
expect(libuvSize.getEffectiveLibuvThreadCount(100000)).to.equal(1024)
48+
})
49+
})
50+
})

0 commit comments

Comments
 (0)