@@ -102,42 +102,43 @@ CallTraceHashTable::~CallTraceHashTable() {
102102}
103103
104104
105- ChunkList CallTraceHashTable::clearTableOnly () {
106- // Wait for all refcount guards to clear before detaching chunks
107- RefCountGuard::waitForAllRefCountsToClear ();
108-
105+ void CallTraceHashTable::decrementCounters () {
109106#ifdef COUNTERS
110107 // Compute and decrement the global counters for everything in this table.
111- // After waitForAllRefCountsToClear() there are no concurrent writers, so
112- // plain iteration (same pattern as collect()) is safe.
108+ // Must only be called after waitForAllRefCountsToClear() so there are no
109+ // concurrent writers and plain iteration is safe.
113110 // Use a set to deduplicate: put() may store the same CallTrace* pointer in
114111 // both a newer and an older table (when findCallTrace finds it in prev()),
115112 // but the counter was only incremented once, so we must only count it once.
116- {
117- const size_t header_size = sizeof (CallTrace) - sizeof (ASGCT_CallFrame);
118- long long freed_bytes = 0 ;
119- long long freed_traces = 0 ;
120- std::unordered_set<CallTrace*> seen;
121- for (LongHashTable *t = _table; t != nullptr ; t = t->prev ()) {
122- u64 *keys = t->keys ();
123- CallTraceSample *values = t->values ();
124- u32 capacity = t->capacity ();
125- for (u32 slot = 0 ; slot < capacity; slot++) {
126- if (keys[slot] != 0 ) {
127- CallTrace *trace = values[slot].acquireTrace ();
128- if (trace != nullptr && trace != CallTraceSample::PREPARING ) {
129- if (seen.insert (trace).second ) {
130- freed_bytes += header_size + trace->num_frames * sizeof (ASGCT_CallFrame);
131- freed_traces++;
132- }
113+ const size_t header_size = sizeof (CallTrace) - sizeof (ASGCT_CallFrame);
114+ long long freed_bytes = 0 ;
115+ long long freed_traces = 0 ;
116+ std::unordered_set<CallTrace*> seen;
117+ for (LongHashTable *t = _table; t != nullptr ; t = t->prev ()) {
118+ u64 *keys = t->keys ();
119+ CallTraceSample *values = t->values ();
120+ u32 capacity = t->capacity ();
121+ for (u32 slot = 0 ; slot < capacity; slot++) {
122+ if (keys[slot] != 0 ) {
123+ CallTrace *trace = values[slot].acquireTrace ();
124+ if (trace != nullptr && trace != CallTraceSample::PREPARING ) {
125+ if (seen.insert (trace).second ) {
126+ freed_bytes += header_size + trace->num_frames * sizeof (ASGCT_CallFrame);
127+ freed_traces++;
133128 }
134129 }
135130 }
136131 }
137- Counters::increment (CALLTRACE_STORAGE_BYTES , -freed_bytes);
138- Counters::increment (CALLTRACE_STORAGE_TRACES , -freed_traces);
139132 }
133+ Counters::increment (CALLTRACE_STORAGE_BYTES , -freed_bytes);
134+ Counters::increment (CALLTRACE_STORAGE_TRACES , -freed_traces);
140135#endif // COUNTERS
136+ }
137+
138+ ChunkList CallTraceHashTable::clearTableOnly () {
139+ // Wait for all refcount guards to clear before detaching chunks
140+ RefCountGuard::waitForAllRefCountsToClear ();
141+ decrementCounters ();
141142
142143 // Clear previous chain pointers to prevent traversal during deallocation
143144 for (LongHashTable *table = _table; table != nullptr ; table = table->prev ()) {
0 commit comments