def __attrs_post_init__(self): r = self._recorder = recorder.Recorder( max_events={ # Allow to store up to 10 threads for 60 seconds at 100 Hz stack.StackSampleEvent: 10 * 60 * 100, stack.StackExceptionSampleEvent: 10 * 60 * 100, # (default buffer size / interval) * export interval memalloc.MemoryAllocSampleEvent: int((memalloc.MemoryCollector._DEFAULT_MAX_EVENTS / memalloc.MemoryCollector._DEFAULT_INTERVAL) * 60), # Do not limit the heap sample size as the number of events is relative to allocated memory anyway memalloc.MemoryHeapSampleEvent: None, }, default_max_events=int( os.environ.get("DD_PROFILING_MAX_EVENTS", recorder.Recorder._DEFAULT_MAX_EVENTS)), ) self._collectors = [ stack.StackCollector(r, tracer=self.tracer), memalloc.MemoryCollector(r), threading.LockCollector(r, tracer=self.tracer), ] exporters = self._build_default_exporters() if exporters: self._scheduler = scheduler.Scheduler( recorder=r, exporters=exporters, before_flush=self._collectors_snapshot)
def __attrs_post_init__(self): r = recorder.Recorder( max_events={ # Allow to store up to 10 threads for 60 seconds at 100 Hz stack.StackSampleEvent: 10 * 60 * 100, stack.StackExceptionSampleEvent: 10 * 60 * 100, # This can generate one event every 0.1s if 100% are taken — though we take 5% by default. # = (60 seconds / 0.1 seconds) memory.MemorySampleEvent: int(60 / 0.1), # (default buffer size / interval) * export interval memalloc.MemoryAllocSampleEvent: int((64 / 0.5) * 60), }, default_max_events=int(os.environ.get("DD_PROFILING_MAX_EVENTS", recorder.Recorder._DEFAULT_MAX_EVENTS)), ) if formats.asbool(os.environ.get("DD_PROFILING_MEMALLOC", "false")): mem_collector = memalloc.MemoryCollector(r) else: mem_collector = memory.MemoryCollector(r) self._collectors = [ stack.StackCollector(r, tracer=self.tracer), mem_collector, exceptions.UncaughtExceptionCollector(r), threading.LockCollector(r), ] exporters = self._build_default_exporters(self.service, self.env, self.version) if exporters: self._scheduler = scheduler.Scheduler(recorder=r, exporters=exporters)
def test_memory_collector(): r = recorder.Recorder() mc = memalloc.MemoryCollector(r) with mc: _allocate_1k() # Make sure we collect at least once mc.periodic() count_object = 0 for event in r.events[memalloc.MemoryAllocSampleEvent]: assert 0 < len(event.frames) <= mc.max_nframe assert event.nframes >= len(event.frames) assert 0 < event.capture_pct <= 100 last_call = event.frames[0] assert event.size > 0 if last_call[2] == "_allocate_1k" and last_call[ 1] == _ALLOC_LINE_NUMBER: assert event.thread_id == _nogevent.main_thread_id assert event.thread_name == "MainThread" count_object += 1 assert event.frames[1][0] == __file__ assert event.frames[1][1] == 143 assert event.frames[1][2] == "test_memory_collector" assert count_object > 0
def test_memalloc_speed(benchmark, heap_sample_size): if heap_sample_size: r = recorder.Recorder() with memalloc.MemoryCollector(r, heap_sample_size=heap_sample_size): benchmark(_allocate_1k) else: benchmark(_allocate_1k)
def __attrs_post_init__(self): r = self._recorder = recorder.Recorder( max_events={ # Allow to store up to 10 threads for 60 seconds at 100 Hz stack.StackSampleEvent: 10 * 60 * 100, stack.StackExceptionSampleEvent: 10 * 60 * 100, # This can generate one event every 0.1s if 100% are taken — though we take 5% by default. # = (60 seconds / 0.1 seconds) memory.MemorySampleEvent: int(60 / 0.1), # (default buffer size / interval) * export interval memalloc.MemoryAllocSampleEvent: int((memalloc.MemoryCollector._DEFAULT_MAX_EVENTS / memalloc.MemoryCollector._DEFAULT_INTERVAL) * 60), # Do not limit the heap sample size as the number of events is relative to allocated memory anyway memalloc.MemoryHeapSampleEvent: None, }, default_max_events=int( os.environ.get("DD_PROFILING_MAX_EVENTS", recorder.Recorder._DEFAULT_MAX_EVENTS)), ) if formats.asbool(os.environ.get("DD_PROFILING_MEMALLOC", "true")): mem_collector = memalloc.MemoryCollector(r) else: mem_collector = memory.MemoryCollector(r) self._collectors = [ stack.StackCollector(r, tracer=self.tracer), mem_collector, threading.LockCollector(r, tracer=self.tracer), ] exporters = self._build_default_exporters(self.tracer, self.url, self.tags, self.service, self.env, self.version) if exporters: self._scheduler = scheduler.Scheduler( recorder=r, exporters=exporters, before_flush=self._collectors_snapshot)
def test_memory_collector_ignore_profiler(ignore_profiler): r = recorder.Recorder() mc = memalloc.MemoryCollector(r, ignore_profiler=ignore_profiler) with mc: object() # Make sure we collect at least once mc.periodic() ok = False for event in r.events[memalloc.MemoryAllocSampleEvent]: for frame in event.frames: if ignore_profiler: assert frame[0] != _periodic.__file__ elif frame[0] == _periodic.__file__: ok = True break if not ignore_profiler: assert ok
def test_memory_collector_ignore_profiler(ignore_profiler): r = recorder.Recorder() mc = memalloc.MemoryCollector(r, ignore_profiler=ignore_profiler) with mc: thread_id = mc._worker.ident object() # Make sure we collect at least once mc.periodic() ok = False for event in r.events[memalloc.MemoryAllocSampleEvent]: if ignore_profiler: assert event.thread_id != thread_id elif event.thread_id == thread_id: ok = True break if not ignore_profiler: assert ok
def test_heap_collector(): heap_sample_size = 1024 r = recorder.Recorder() mc = memalloc.MemoryCollector(r, heap_sample_size=heap_sample_size) with mc: keep_me = _allocate_1k() events = mc.snapshot() assert len(events) == 1 assert len(events[0]) >= 1 del keep_me for event in events[0]: assert 0 < len(event.frames) <= mc.max_nframe assert event.nframes >= len(event.frames) assert event.sample_size == heap_sample_size assert len(event.frames) >= 1 assert event.size > 0 assert event.thread_id > 0 assert isinstance(event.thread_name, str)
def test_memory_collector_ignore_profiler( ignore_profiler, # type: bool ): # type: (...) -> None r = recorder.Recorder() mc = memalloc.MemoryCollector(r, ignore_profiler=ignore_profiler) quit_thread = threading.Event() with mc: def alloc(): _allocate_1k() quit_thread.wait() alloc_thread = threading.Thread(name="allocator", target=alloc) if ignore_profiler: alloc_thread._ddtrace_profiling_ignore = True alloc_thread.start() thread_id = alloc_thread.ident # Make sure we collect at least once mc.periodic() # We need to wait for the data collection to happen so it gets the `_ddtrace_profiling_ignore` Thread attribute from # the global thread list. quit_thread.set() alloc_thread.join() for event in r.events[memalloc.MemoryAllocSampleEvent]: if ignore_profiler: assert event.thread_id != thread_id elif event.thread_id == thread_id: break else: assert ignore_profiler, "No allocation event was found with the allocator thread"