Skip to content

Commit e856fb0

Browse files
authored
Make sure space profiler (almost) always goes first (#6808)
1 parent 53670c5 commit e856fb0

File tree

2 files changed

+69
-13
lines changed

2 files changed

+69
-13
lines changed

packages/dd-trace/src/profiling/config.js

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,29 +269,51 @@ module.exports = { Config }
269269
function getProfilers ({
270270
DD_PROFILING_HEAP_ENABLED, DD_PROFILING_WALLTIME_ENABLED, DD_PROFILING_PROFILERS
271271
}) {
272-
// First consider "legacy" DD_PROFILING_PROFILERS env variable, defaulting to wall + space
272+
// First consider "legacy" DD_PROFILING_PROFILERS env variable, defaulting to space + wall
273273
// Use a Set to avoid duplicates
274-
const profilers = new Set((DD_PROFILING_PROFILERS ?? 'wall,space').split(','))
274+
// NOTE: space profiler is very deliberately in the first position. This way
275+
// when profilers are stopped sequentially one after the other to create
276+
// snapshots the space profile won't include memory taken by profiles created
277+
// before it in the sequence. That memory is ultimately transient and will be
278+
// released when all profiles are subsequently encoded.
279+
const profilers = new Set((DD_PROFILING_PROFILERS ?? 'space,wall').split(','))
280+
281+
let spaceExplicitlyEnabled = false
282+
// Add/remove space depending on the value of DD_PROFILING_HEAP_ENABLED
283+
if (DD_PROFILING_HEAP_ENABLED != null) {
284+
if (isTrue(DD_PROFILING_HEAP_ENABLED)) {
285+
if (!profilers.has('space')) {
286+
profilers.add('space')
287+
spaceExplicitlyEnabled = true
288+
}
289+
} else if (isFalse(DD_PROFILING_HEAP_ENABLED)) {
290+
profilers.delete('space')
291+
}
292+
}
275293

276294
// Add/remove wall depending on the value of DD_PROFILING_WALLTIME_ENABLED
277295
if (DD_PROFILING_WALLTIME_ENABLED != null) {
278296
if (isTrue(DD_PROFILING_WALLTIME_ENABLED)) {
279297
profilers.add('wall')
280298
} else if (isFalse(DD_PROFILING_WALLTIME_ENABLED)) {
281299
profilers.delete('wall')
300+
profilers.delete('cpu') // remove alias too
282301
}
283302
}
284303

285-
// Add/remove wall depending on the value of DD_PROFILING_HEAP_ENABLED
286-
if (DD_PROFILING_HEAP_ENABLED != null) {
287-
if (isTrue(DD_PROFILING_HEAP_ENABLED)) {
288-
profilers.add('space')
289-
} else if (isFalse(DD_PROFILING_HEAP_ENABLED)) {
290-
profilers.delete('space')
304+
const profilersArray = [...profilers]
305+
// If space was added through DD_PROFILING_HEAP_ENABLED, ensure it is in the
306+
// first position. Basically, the only way for it not to be in the first
307+
// position is if it was explicitly specified in a different position in
308+
// DD_PROFILING_PROFILERS.
309+
if (spaceExplicitlyEnabled) {
310+
const spaceIdx = profilersArray.indexOf('space')
311+
if (spaceIdx > 0) {
312+
profilersArray.splice(spaceIdx, 1)
313+
profilersArray.unshift('space')
291314
}
292315
}
293-
294-
return [...profilers]
316+
return profilersArray
295317
}
296318

297319
function getExportStrategy (name, options) {

packages/dd-trace/test/profiling/config.spec.js

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ describe('config', () => {
5252

5353
expect(config.logger).to.be.an.instanceof(ConsoleLogger)
5454
expect(config.exporters[0]).to.be.an.instanceof(AgentExporter)
55-
expect(config.profilers[0]).to.be.an.instanceof(WallProfiler)
56-
expect(config.profilers[0].codeHotspotsEnabled()).to.equal(samplingContextsAvailable)
57-
expect(config.profilers[1]).to.be.an.instanceof(SpaceProfiler)
55+
expect(config.profilers[0]).to.be.an.instanceof(SpaceProfiler)
56+
expect(config.profilers[1]).to.be.an.instanceof(WallProfiler)
57+
expect(config.profilers[1].codeHotspotsEnabled()).to.equal(samplingContextsAvailable)
5858
expect(config.v8ProfilerBugWorkaroundEnabled).true
5959
expect(config.cpuProfilingEnabled).to.equal(samplingContextsAvailable)
6060
expect(config.uploadCompression.method).to.equal('gzip')
@@ -177,6 +177,40 @@ describe('config', () => {
177177
expect(config.profilers[0]).to.be.an.instanceOf(SpaceProfiler)
178178
})
179179

180+
it('should ensure space profiler is ordered first with DD_PROFILING_HEAP_ENABLED', () => {
181+
process.env = {
182+
DD_PROFILING_PROFILERS: 'wall',
183+
DD_PROFILING_HEAP_ENABLED: '1'
184+
}
185+
const options = {
186+
logger: nullLogger
187+
}
188+
189+
const config = new Config(options)
190+
191+
expect(config.profilers).to.be.an('array')
192+
expect(config.profilers.length).to.equal(2 + (samplingContextsAvailable ? 1 : 0))
193+
expect(config.profilers[0]).to.be.an.instanceOf(SpaceProfiler)
194+
expect(config.profilers[1]).to.be.an.instanceOf(WallProfiler)
195+
})
196+
197+
it('should ensure space profiler order is preserved when explicitly set with DD_PROFILING_PROFILERS', () => {
198+
process.env = {
199+
DD_PROFILING_PROFILERS: 'wall,space',
200+
DD_PROFILING_HEAP_ENABLED: '1'
201+
}
202+
const options = {
203+
logger: nullLogger
204+
}
205+
206+
const config = new Config(options)
207+
208+
expect(config.profilers).to.be.an('array')
209+
expect(config.profilers.length).to.equal(2 + (samplingContextsAvailable ? 1 : 0))
210+
expect(config.profilers[0]).to.be.an.instanceOf(WallProfiler)
211+
expect(config.profilers[1]).to.be.an.instanceOf(SpaceProfiler)
212+
})
213+
180214
it('should be able to read some env vars', () => {
181215
const oldenv = process.env
182216
process.env = {

0 commit comments

Comments
 (0)