Skip to content

Commit

Permalink
[PROF-9470] Enable "heap clean after GC" profiler optimization by def…
Browse files Browse the repository at this point in the history
…ault

**What does this PR do?**

This PR changes the optimization added in #4020 to be enabled by
default.

I've collected a fresh set of benchmarking results for this feature in
[this google doc](https://docs.google.com/document/d/143jmyzB7rMJ9W2hKN0JoDbjo2m3oCVCzvPToHVjLRAM/edit?tab=t.0#heading=h.f00wz5x8kwg6).

The TL;DR is that results seem to be... very close. E.g. sometimes we
slightly improve things, but often the numbers seem too close to tell.

But on the other hand this also means that there are no regressions,
and thus no reason not to enable the feature by default.

**Motivation:**

As a recap, without this optimization, the Ruby heap profiler works
by sampling allocated objects, collecting and keeping metadata about
these objects (stack trace, etc). Then, at serialization time
(every 60 seconds), the profiler checks which objects are still alive;
any objects still alive get included in the heap profile; any objects
that have since been garbage collected get their metadata dropped.

The above scheme has a weak-point: some objects are allocated and
almost immediately become garbage collected. Because the profiler
only checks for object liveness at serialization time, this can mean
that in the extreme, an object born and collected at the beginning
of the profiling period can still be tracked for almost 60 seconds
until the profiler finally figures out that the object is no longer
alive.

This has two consequences:
1. The profiler uses more memory, since it’s collecting metadata
   for already-dead objects
2. The profiler has more work to do at the end of the 60-second
    period – it needs to check an entire 60 seconds of sampled objects

The heap profiling clean after GC optimization adds an extra
mechanism that, based on Ruby GC activity, triggers periodic checking
of young objects (e.g. objects that have been alive for few GC
generations). Thus:

a. The profiler identifies and clears garbage objects faster,
   thus overall needing less memory
b. The profiler has less work to do at the end of the 60-second
    period
    ...trading it off with a smaller periodic pass

**Additional Notes:**

I've also removed the separate benchmarking configuration, to
avoid having too many long-running benchmarking variants.

**How to test the change?**

I've updated the specs for the setting, and the optimization itself
has existing test coverage that was added back in #4020.
  • Loading branch information
ivoanjo committed Nov 7, 2024
1 parent f679de4 commit da099a9
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 17 deletions.
10 changes: 0 additions & 10 deletions .gitlab/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,6 @@ only-profiling-heap:
DD_PROFILING_EXPERIMENTAL_HEAP_ENABLED: "true"
ADD_TO_GEMFILE: "gem 'datadog', github: 'datadog/dd-trace-rb', ref: '$CI_COMMIT_SHA'"

only-profiling-heap-clean-after-gc:
extends: .benchmarks
variables:
DD_BENCHMARKS_CONFIGURATION: only-profiling
DD_PROFILING_ENABLED: "true"
DD_PROFILING_ALLOCATION_ENABLED: "true"
DD_PROFILING_EXPERIMENTAL_HEAP_ENABLED: "true"
DD_PROFILING_HEAP_CLEAN_AFTER_GC_ENABLED: "true"
ADD_TO_GEMFILE: "gem 'datadog', github: 'datadog/dd-trace-rb', ref: '$CI_COMMIT_SHA'"

only-profiling-gvl:
extends: .benchmarks
variables:
Expand Down
6 changes: 3 additions & 3 deletions lib/datadog/core/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -518,13 +518,13 @@ def initialize(*_)
# Controls if the heap profiler should attempt to clean young objects after GC, rather than just at
# serialization time. This lowers memory usage and high percentile latency.
#
# Only takes effect when used together with `gc_enabled: true` and `experimental_heap_enabled: true`.
# Only has effect when used together with `gc_enabled: true` and `experimental_heap_enabled: true`.
#
# @default false
# @default true
option :heap_clean_after_gc_enabled do |o|
o.type :bool
o.env 'DD_PROFILING_HEAP_CLEAN_AFTER_GC_ENABLED'
o.default false
o.default true
end
end

Expand Down
8 changes: 4 additions & 4 deletions spec/datadog/core/configuration/settings_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@
context 'is not defined' do
let(:environment) { nil }

it { is_expected.to be false }
it { is_expected.to be true }
end

[true, false].each do |value|
Expand All @@ -947,10 +947,10 @@

describe '#heap_clean_after_gc_enabled=' do
it 'updates the #heap_clean_after_gc_enabled setting' do
expect { settings.profiling.advanced.heap_clean_after_gc_enabled = true }
expect { settings.profiling.advanced.heap_clean_after_gc_enabled = false }
.to change { settings.profiling.advanced.heap_clean_after_gc_enabled }
.from(false)
.to(true)
.from(true)
.to(false)
end
end

Expand Down

0 comments on commit da099a9

Please sign in to comment.