Skip to content

Memory leak with Sentry.Profiling 6.6.0 on Linux: TraceEvent call-stack/method index tables accumulate unboundedly under traffic (~0.6 GB/day to OOM) #5469

Description

@therickfactr

Package

Sentry.Profiling

.NET Flavor

.NET

.NET Version

8.0

OS

Linux

SDK Version

6.6.0 (Sentry.AspNetCore 6.6.0 + Sentry.Profiling 6.6.0)

Self-Hosted Sentry Version

No response (SaaS)

Steps to Reproduce

  1. ASP.NET Core service on Linux x64 (Rocky 9, kernel 5.14), 8 GB VM, systemd-hosted, builder.WebHost.UseSentry(...) with options.AddProfilingIntegration().
  2. TracesSampleRate: 0.1, ProfilesSampleRate: 0.1.
  3. Run under real production traffic (an idle instance does not reproduce — sampled transactions drive it).
  4. Watch process RSS over days.

Expected Result

Profiling overhead reaches a bounded steady state.

Actual Result

RSS grows ~0.6 GB/day under steady traffic until kernel OOM-kill at ~6.1 GB anon RSS after ~8 days of uptime. Growth rate is traffic-proportional (~100 MiB/hr at evening peak, less overnight).

dotnet-gcdump on the live process (t+5.5 h after a restart, working set 1581 MiB and climbing) shows 478 MB live heap / 8.67 M objects, and the top retained large types are all Microsoft.Diagnostics.Tracing (TraceEvent) bookkeeping:

   Object Bytes     Count  Type
     35,087,256         1  CallStackInfo[]  [Microsoft.Diagnostics.Tracing.TraceEvent.dll]
     35,087,256         1  System.Collections.Generic.List<Microsoft.Diagnostics.Tracing.Etlx.CallStackIndex>[]
      2,548,664         1  MethodInfo[]  [Microsoft.Diagnostics.Tracing.TraceEvent.dll]
      2,548,536         1  CodeAddressInfo[]  [Microsoft.Diagnostics.Tracing.TraceEvent.dll]
      2,172,576         1  Entry<System.Int64,TraceCodeAddresses+ILMapIndex>[]
      1,810,368         1  Entry<System.UInt64,CodeAddressIndex>[]
      1,048,600         1  MethodLoadUnloadVerboseTraceData[]  [TraceEvent]
        876,536         1  TraceMethod[]  [TraceEvent]
        849,528         1  ILToNativeMap[]  [TraceEvent]
        424,776         1  CodeAddressIndex[]  [TraceEvent]
        161,984         1  Entry<System.Int32,EventPipe.StackCache+StackMarker>[]

(These are the >100 KB single arrays; the remaining growth is millions of small entries in the same structures.)

A/B on the identical build: set ProfilesSampleRate: 0 and restart → t+10 h working set 477 MiB and falling; gcdump shows 31 MB live / 470 k objects with zero TraceEvent types. Leak fully cured by disabling profiling alone (tracing, logs, error reporting all left enabled).

Analysis

The continuous in-process EventPipe/TraceEvent session backing transaction profiling accumulates call-stack, code-address, and IL-map index tables (CallStackInfo, TraceCodeAddresses maps, ILToNativeMap, StackCache) for the life of the session, proportional to the diversity/volume of sampled stacks. They are never trimmed.

Related history — all distinct mechanisms, and all already present in 6.6.0:

As far as I can tell this steady-state TraceEvent index accumulation has no existing open or closed issue.

Happy to attach both full gcdump type histograms (with-profiling vs without) if useful.

Metadata

Metadata

Assignees

Labels

.NETPull requests that update .net codeBugSomething isn't workingProfiles

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions