| 3202 | } |
| 3203 | |
| 3204 | void |
| 3205 | rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats) { |
| 3206 | memset(stats, 0, sizeof(rpmalloc_thread_statistics_t)); |
| 3207 | heap_t* heap = get_thread_heap_raw(); |
| 3208 | if (!heap) |
| 3209 | return; |
| 3210 | |
| 3211 | for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { |
| 3212 | size_class_t* size_class = _memory_size_class + iclass; |
| 3213 | span_t* span = heap->size_class[iclass].partial_span; |
| 3214 | while (span) { |
| 3215 | size_t free_count = span->list_size; |
| 3216 | size_t block_count = size_class->block_count; |
| 3217 | if (span->free_list_limit < block_count) |
| 3218 | block_count = span->free_list_limit; |
| 3219 | free_count += (block_count - span->used_count); |
| 3220 | stats->sizecache += free_count * size_class->block_size; |
| 3221 | span = span->next; |
| 3222 | } |
| 3223 | } |
| 3224 | |
| 3225 | #if ENABLE_THREAD_CACHE |
| 3226 | for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { |
| 3227 | span_cache_t* span_cache; |
| 3228 | if (!iclass) |
| 3229 | span_cache = &heap->span_cache; |
| 3230 | else |
| 3231 | span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); |
| 3232 | stats->spancache += span_cache->count * (iclass + 1) * _memory_span_size; |
| 3233 | } |
| 3234 | #endif |
| 3235 | |
| 3236 | span_t* deferred = (span_t*)atomic_load_ptr(&heap->span_free_deferred); |
| 3237 | while (deferred) { |
| 3238 | if (deferred->size_class != SIZE_CLASS_HUGE) |
| 3239 | stats->spancache += (size_t)deferred->span_count * _memory_span_size; |
| 3240 | deferred = (span_t*)deferred->free_list; |
| 3241 | } |
| 3242 | |
| 3243 | #if ENABLE_STATISTICS |
| 3244 | stats->thread_to_global = (size_t)atomic_load64(&heap->thread_to_global); |
| 3245 | stats->global_to_thread = (size_t)atomic_load64(&heap->global_to_thread); |
| 3246 | |
| 3247 | for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { |
| 3248 | stats->span_use[iclass].current = (size_t)atomic_load32(&heap->span_use[iclass].current); |
| 3249 | stats->span_use[iclass].peak = (size_t)atomic_load32(&heap->span_use[iclass].high); |
| 3250 | stats->span_use[iclass].to_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_global); |
| 3251 | stats->span_use[iclass].from_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_global); |
| 3252 | stats->span_use[iclass].to_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache); |
| 3253 | stats->span_use[iclass].from_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache); |
| 3254 | stats->span_use[iclass].to_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved); |
| 3255 | stats->span_use[iclass].from_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved); |
| 3256 | stats->span_use[iclass].map_calls = (size_t)atomic_load32(&heap->span_use[iclass].spans_map_calls); |
| 3257 | } |
| 3258 | for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { |
| 3259 | stats->size_use[iclass].alloc_current = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_current); |
| 3260 | stats->size_use[iclass].alloc_peak = (size_t)heap->size_class_use[iclass].alloc_peak; |
| 3261 | stats->size_use[iclass].alloc_total = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_total); |
nothing calls this directly
no test coverage detected