diff --git a/ddtrace/profiling/collector/_memalloc.c b/ddtrace/profiling/collector/_memalloc.c index 90af738399c..b213ae1b595 100644 --- a/ddtrace/profiling/collector/_memalloc.c +++ b/ddtrace/profiling/collector/_memalloc.c @@ -17,8 +17,6 @@ typedef struct PyMemAllocatorEx pymem_allocator_obj; /* The domain we are tracking */ PyMemAllocatorDomain domain; - /* The maximum number of events for allocation tracking */ - uint16_t max_events; /* The maximum number of frames collected in stack traces */ uint16_t max_nframe; @@ -93,15 +91,16 @@ memalloc_realloc(void* ctx, void* ptr, size_t new_size) } PyDoc_STRVAR(memalloc_start__doc__, - "start($module, max_nframe, max_events, heap_sample_size)\n" + "start($module, max_nframe, heap_sample_interval)\n" "--\n" "\n" "Start tracing Python memory allocations.\n" "\n" "Sets the maximum number of frames stored in the traceback of a\n" - "trace to max_nframe and the maximum number of events to max_events.\n" - "Set heap_sample_size to the granularity of the heap profiler, in bytes.\n" - "If heap_sample_size is set to 0, it is disabled entirely.\n"); + "trace to max_nframe.\n" + "Sets the average number of bytes allocated between samples to\n" + "heap_sample_interval.\n" + "If heap_sample_interval is set to 0, it is disabled entirely.\n"); static PyObject* memalloc_start(PyObject* Py_UNUSED(module), PyObject* args) { @@ -117,11 +116,11 @@ memalloc_start(PyObject* Py_UNUSED(module), PyObject* args) srand(atoi(val)); } - long max_nframe, max_events; + long max_nframe; long long int heap_sample_size; /* Store short ints in ints so we're sure they fit */ - if (!PyArg_ParseTuple(args, "llL", &max_nframe, &max_events, &heap_sample_size)) + if (!PyArg_ParseTuple(args, "lL", &max_nframe, &heap_sample_size)) return NULL; if (max_nframe < 1 || max_nframe > TRACEBACK_MAX_NFRAME) { @@ -131,13 +130,6 @@ memalloc_start(PyObject* Py_UNUSED(module), PyObject* args) global_memalloc_ctx.max_nframe = (uint16_t)max_nframe; - if (max_events < 1 || max_events > TRACEBACK_ARRAY_MAX_COUNT) { - PyErr_Format(PyExc_ValueError, "the number of events must be in range [1; %u]", TRACEBACK_ARRAY_MAX_COUNT); - return NULL; - } - - global_memalloc_ctx.max_events = (uint16_t)max_events; - if (heap_sample_size < 0 || heap_sample_size > MAX_HEAP_SAMPLE_SIZE) { PyErr_Format(PyExc_ValueError, "the heap sample size must be in range [0; %u]", MAX_HEAP_SAMPLE_SIZE); return NULL; diff --git a/ddtrace/profiling/collector/_memalloc.pyi b/ddtrace/profiling/collector/_memalloc.pyi index 684e0a4ec24..5fa33dd1061 100644 --- a/ddtrace/profiling/collector/_memalloc.pyi +++ b/ddtrace/profiling/collector/_memalloc.pyi @@ -9,6 +9,6 @@ StackType = event.StackTraceType # (stack, thread_id) TracebackType = typing.Tuple[StackType, int] -def start(max_nframe: int, max_events: int, heap_sample_size: int) -> None: ... +def start(max_nframe: int, heap_sample_interval: int) -> None: ... def stop() -> None: ... def heap() -> typing.List[typing.Tuple[TracebackType, int, int, int]]: ... diff --git a/ddtrace/profiling/collector/memalloc.py b/ddtrace/profiling/collector/memalloc.py index 992dcbcc4e2..ebfb5f0ef2c 100644 --- a/ddtrace/profiling/collector/memalloc.py +++ b/ddtrace/profiling/collector/memalloc.py @@ -30,21 +30,14 @@ class MemoryCollector(collector.PeriodicCollector): """Memory allocation collector.""" - _DEFAULT_MAX_EVENTS = 16 - _DEFAULT_INTERVAL = 0.5 - def __init__( self, - _interval: float = _DEFAULT_INTERVAL, - _max_events: Optional[int] = None, max_nframe: Optional[int] = None, heap_sample_size: Optional[int] = None, ignore_profiler: Optional[bool] = None, ): super().__init__() - self._interval: float = _interval # TODO make this dynamic based on the 1. interval and 2. the max number of events allowed in the Recorder - self._max_events: int = _max_events if _max_events is not None else config.memory.events_buffer self.max_nframe: int = max_nframe if max_nframe is not None else config.max_frames self.heap_sample_size: int = heap_sample_size if heap_sample_size is not None else config.heap.sample_size self.ignore_profiler: bool = ignore_profiler if ignore_profiler is not None else config.ignore_profiler @@ -56,13 +49,13 @@ def _start_service(self): raise collector.CollectorUnavailable try: - _memalloc.start(self.max_nframe, self._max_events, self.heap_sample_size) + _memalloc.start(self.max_nframe, self.heap_sample_size) except RuntimeError: # This happens on fork because we don't call the shutdown hook since # the thread responsible for doing so is not running in the child # process. Therefore we stop and restart the collector instead. _memalloc.stop() - _memalloc.start(self.max_nframe, self._max_events, self.heap_sample_size) + _memalloc.start(self.max_nframe, self.heap_sample_size) super(MemoryCollector, self)._start_service() diff --git a/ddtrace/settings/profiling.py b/ddtrace/settings/profiling.py index 006519aaa34..b1684b782d5 100644 --- a/ddtrace/settings/profiling.py +++ b/ddtrace/settings/profiling.py @@ -155,14 +155,6 @@ class ProfilingConfig(DDConfig): help="", ) - max_events = DDConfig.v( - int, - "max_events", - default=16384, - help_type="Integer", - help="", - ) - upload_interval = DDConfig.v( float, "upload_interval", @@ -339,7 +331,7 @@ class ProfilingConfigHeap(DDConfig): "sample_size", default=None, help_type="Integer", - help="", + help="Average number of bytes allocated between memory profiler samples", ) sample_size = DDConfig.d(int, _derive_default_heap_sample_size) diff --git a/tests/profiling/collector/test_memalloc.py b/tests/profiling/collector/test_memalloc.py index dcccc76d832..54f1997a46b 100644 --- a/tests/profiling/collector/test_memalloc.py +++ b/tests/profiling/collector/test_memalloc.py @@ -19,40 +19,37 @@ def test_start_twice(): - _memalloc.start(64, 1000, 512) + _memalloc.start(64, 512) with pytest.raises(RuntimeError): - _memalloc.start(64, 1000, 512) + _memalloc.start(64, 512) _memalloc.stop() def test_start_wrong_arg(): - with pytest.raises(TypeError, match="function takes exactly 3 arguments \\(1 given\\)"): + with pytest.raises(TypeError, match="function takes exactly 2 arguments \\(1 given\\)"): _memalloc.start(2) with pytest.raises(ValueError, match="the number of frames must be in range \\[1; 65535\\]"): - _memalloc.start(429496, 1000, 1) + _memalloc.start(429496, 1) with pytest.raises(ValueError, match="the number of frames must be in range \\[1; 65535\\]"): - _memalloc.start(-1, 1000, 1) - - with pytest.raises(ValueError, match="the number of events must be in range \\[1; 65535\\]"): - _memalloc.start(64, -1, 1) + _memalloc.start(-1, 1) with pytest.raises( ValueError, match="the heap sample size must be in range \\[0; 4294967295\\]", ): - _memalloc.start(64, 1000, -1) + _memalloc.start(64, -1) with pytest.raises( ValueError, match="the heap sample size must be in range \\[0; 4294967295\\]", ): - _memalloc.start(64, 1000, 345678909876) + _memalloc.start(64, 345678909876) def test_start_stop(): - _memalloc.start(1, 1, 1) + _memalloc.start(1, 1) _memalloc.stop() @@ -69,7 +66,7 @@ def _pre_allocate_1k(): def test_iter_events(): max_nframe = 32 - collector = memalloc.MemoryCollector(max_nframe=max_nframe, _max_events=10000, heap_sample_size=64) + collector = memalloc.MemoryCollector(max_nframe=max_nframe, heap_sample_size=64) with collector: _allocate_1k() samples = collector.test_snapshot() @@ -105,7 +102,7 @@ def test_iter_events(): def test_iter_events_dropped(): max_nframe = 32 - collector = memalloc.MemoryCollector(max_nframe=max_nframe, _max_events=100, heap_sample_size=64) + collector = memalloc.MemoryCollector(max_nframe=max_nframe, heap_sample_size=64) with collector: _allocate_1k() samples = collector.test_snapshot() @@ -130,7 +127,7 @@ def test_iter_events_not_started(): def test_iter_events_multi_thread(): max_nframe = 32 t = threading.Thread(target=_allocate_1k) - collector = memalloc.MemoryCollector(max_nframe=max_nframe, _max_events=10000, heap_sample_size=64) + collector = memalloc.MemoryCollector(max_nframe=max_nframe, heap_sample_size=64) with collector: _allocate_1k() t.start() @@ -179,7 +176,7 @@ def test_iter_events_multi_thread(): def test_heap(): max_nframe = 32 - collector = memalloc.MemoryCollector(max_nframe=max_nframe, _max_events=10000, heap_sample_size=1024) + collector = memalloc.MemoryCollector(max_nframe=max_nframe, heap_sample_size=1024) with collector: _test_heap_impl(collector, max_nframe) @@ -298,7 +295,7 @@ def _test_heap_impl(collector, max_nframe): def test_heap_stress(): # This should run for a few seconds, and is enough to spot potential segfaults. - _memalloc.start(64, 64, 1024) + _memalloc.start(64, 1024) try: x = [] diff --git a/tests/profiling_v2/collector/test_memalloc.py b/tests/profiling_v2/collector/test_memalloc.py index b98e2629b01..832da62aa2d 100644 --- a/tests/profiling_v2/collector/test_memalloc.py +++ b/tests/profiling_v2/collector/test_memalloc.py @@ -254,7 +254,7 @@ def test_heap_profiler_sampling_accuracy(sample_interval): # pass for an arbitrary seed. old = os.environ.get("_DD_MEMALLOC_DEBUG_RNG_SEED") os.environ["_DD_MEMALLOC_DEBUG_RNG_SEED"] = "42" - _memalloc.start(32, 1000, sample_interval) + _memalloc.start(32, sample_interval) # Put the env var back in the state we found it if old is not None: os.environ["_DD_MEMALLOC_DEBUG_RNG_SEED"] = old @@ -679,7 +679,7 @@ def test_memory_collector_allocation_during_shutdown(): from ddtrace.profiling.collector import _memalloc - _memalloc.start(32, 1000, 512) + _memalloc.start(32, 512) shutdown_event = threading.Event() allocation_thread = None diff --git a/tests/telemetry/test_writer.py b/tests/telemetry/test_writer.py index e88f07d3eb9..5e289c457c7 100644 --- a/tests/telemetry/test_writer.py +++ b/tests/telemetry/test_writer.py @@ -436,7 +436,6 @@ def test_app_started_event_configuration_override(test_agent_session, run_python {"name": "DD_PROFILING_IGNORE_PROFILER", "origin": "default", "value": False}, {"name": "DD_PROFILING_LOCK_ENABLED", "origin": "env_var", "value": False}, {"name": "DD_PROFILING_LOCK_NAME_INSPECT_DIR", "origin": "default", "value": True}, - {"name": "DD_PROFILING_MAX_EVENTS", "origin": "default", "value": 16384}, {"name": "DD_PROFILING_MAX_FRAMES", "origin": "env_var", "value": 512}, {"name": "DD_PROFILING_MAX_TIME_USAGE_PCT", "origin": "default", "value": 1.0}, {"name": "DD_PROFILING_MEMORY_ENABLED", "origin": "env_var", "value": False},