@@ -102,9 +102,48 @@ CallTraceHashTable::~CallTraceHashTable() {
102102}
103103
104104
105+ void CallTraceHashTable::decrementCounters () {
106+ #ifdef COUNTERS
107+ // Compute and decrement the global counters for everything in this table.
108+ // Must only be called after waitForAllRefCountsToClear() so there are no
109+ // concurrent writers and plain iteration is safe.
110+ // Use a set to deduplicate: put() may store the same CallTrace* pointer in
111+ // both a newer and an older table (when findCallTrace finds it in prev()),
112+ // but the counter was only incremented once, so we must only count it once.
113+ const size_t header_size = sizeof (CallTrace) - sizeof (ASGCT_CallFrame);
114+ long long freed_bytes = 0 ;
115+ long long freed_traces = 0 ;
116+ size_t estimated_entries = 0 ;
117+ for (LongHashTable *t = _table; t != nullptr ; t = t->prev ()) {
118+ estimated_entries += t->size ();
119+ }
120+ std::unordered_set<CallTrace*> seen;
121+ seen.reserve (estimated_entries);
122+ for (LongHashTable *t = _table; t != nullptr ; t = t->prev ()) {
123+ u64 *keys = t->keys ();
124+ CallTraceSample *values = t->values ();
125+ u32 capacity = t->capacity ();
126+ for (u32 slot = 0 ; slot < capacity; slot++) {
127+ if (keys[slot] != 0 ) {
128+ CallTrace *trace = values[slot].acquireTrace ();
129+ if (trace != nullptr && trace != CallTraceSample::PREPARING ) {
130+ if (seen.insert (trace).second ) {
131+ freed_bytes += header_size + trace->num_frames * sizeof (ASGCT_CallFrame);
132+ freed_traces++;
133+ }
134+ }
135+ }
136+ }
137+ }
138+ Counters::increment (CALLTRACE_STORAGE_BYTES , -freed_bytes);
139+ Counters::increment (CALLTRACE_STORAGE_TRACES , -freed_traces);
140+ #endif // COUNTERS
141+ }
142+
105143ChunkList CallTraceHashTable::clearTableOnly () {
106144 // Wait for all refcount guards to clear before detaching chunks
107145 RefCountGuard::waitForAllRefCountsToClear ();
146+ decrementCounters ();
108147
109148 // Clear previous chain pointers to prevent traversal during deallocation
110149 for (LongHashTable *table = _table; table != nullptr ; table = table->prev ()) {
@@ -424,7 +463,7 @@ void CallTraceHashTable::putWithExistingId(CallTrace* source_trace, u64 weight)
424463 table->values ()[slot].setTrace (copied_trace);
425464 Counters::increment (CALLTRACE_STORAGE_BYTES , total_size);
426465 Counters::increment (CALLTRACE_STORAGE_TRACES );
427-
466+
428467 // Increment table size
429468 u32 new_size = table->incSize ();
430469 probe.updateCapacity (new_size);
0 commit comments