@@ -21,6 +21,7 @@ terms of the MIT license. A copy of the license can be found in the file
2121// --------------------------------------------------------------------------
2222
2323
24+ #include <mimalloc-stats.h>
2425#include <stddef.h> // ptrdiff_t
2526#include <stdint.h> // uintptr_t, uint16_t, etc
2627#include "atomic.h" // _Atomic
@@ -515,6 +516,61 @@ struct mi_heap_s {
515516};
516517
517518
519+ // ------------------------------------------------------
520+ // Sub processes do not reclaim or visit segments
521+ // from other sub processes. These are essentially the
522+ // static variables of a process.
523+ // ------------------------------------------------------
524+
525+ struct mi_subproc_s {
526+ _Atomic (size_t ) abandoned_count ; // count of abandoned segments for this sub-process
527+ _Atomic (size_t ) abandoned_os_list_count ; // count of abandoned segments in the os-list
528+ mi_lock_t abandoned_os_lock ; // lock for the abandoned os segment list (outside of arena's) (this lock protect list operations)
529+ mi_lock_t abandoned_os_visit_lock ; // ensure only one thread per subproc visits the abandoned os list
530+ mi_segment_t * abandoned_os_list ; // doubly-linked list of abandoned segments outside of arena's (in OS allocated memory)
531+ mi_segment_t * abandoned_os_list_tail ; // the tail-end of the list
532+ mi_memid_t memid ; // provenance of this memory block
533+ };
534+
535+
536+ // ------------------------------------------------------
537+ // Thread Local data
538+ // ------------------------------------------------------
539+
540+ // Milliseconds as in `int64_t` to avoid overflows
541+ typedef int64_t mi_msecs_t ;
542+
543+ // Queue of segments
544+ typedef struct mi_segment_queue_s {
545+ mi_segment_t * first ;
546+ mi_segment_t * last ;
547+ } mi_segment_queue_t ;
548+
549+ // Segments thread local data
550+ typedef struct mi_segments_tld_s {
551+ mi_segment_queue_t small_free ; // queue of segments with free small pages
552+ mi_segment_queue_t medium_free ; // queue of segments with free medium pages
553+ mi_page_queue_t pages_purge ; // queue of freed pages that are delay purged
554+ size_t count ; // current number of segments;
555+ size_t peak_count ; // peak number of segments
556+ size_t current_size ; // current size of all segments
557+ size_t peak_size ; // peak size of all segments
558+ size_t reclaim_count ;// number of reclaimed (abandoned) segments
559+ mi_subproc_t * subproc ; // sub-process this thread belongs to.
560+ mi_stats_t * stats ; // points to tld stats
561+ } mi_segments_tld_t ;
562+
563+ // Thread local data
564+ struct mi_tld_s {
565+ unsigned long long heartbeat ; // monotonic heartbeat count
566+ bool recurse ; // true if deferred was called; used to prevent infinite recursion.
567+ mi_heap_t * heap_backing ; // backing heap of this thread (cannot be deleted)
568+ mi_heap_t * heaps ; // list of heaps in this thread (so we can abandon all when the thread terminates)
569+ mi_segments_tld_t segments ; // segment tld
570+ mi_stats_t stats ; // statistics
571+ };
572+
573+
518574
519575// ------------------------------------------------------
520576// Debug
@@ -550,10 +606,10 @@ void _mi_assert_fail(const char* assertion, const char* fname, unsigned int line
550606#define mi_assert_expensive (x )
551607#endif
552608
609+
553610// ------------------------------------------------------
554611// Statistics
555612// ------------------------------------------------------
556-
557613#ifndef MI_STAT
558614#if (MI_DEBUG > 0 )
559615#define MI_STAT 2
@@ -562,64 +618,6 @@ void _mi_assert_fail(const char* assertion, const char* fname, unsigned int line
562618#endif
563619#endif
564620
565- typedef struct mi_stat_count_s {
566- int64_t total ;
567- int64_t peak ;
568- int64_t current ;
569- } mi_stat_count_t ;
570-
571- typedef struct mi_stat_counter_s {
572- int64_t total ;
573- } mi_stat_counter_t ;
574-
575- typedef struct mi_stats_s {
576- mi_stat_count_t pages ; // count of mimalloc pages
577- mi_stat_count_t reserved ; // reserved memory bytes
578- mi_stat_count_t committed ; // committed bytes
579- mi_stat_count_t reset ; // reset bytes
580- mi_stat_count_t purged ; // purged bytes
581- mi_stat_count_t page_committed ; // committed memory inside pages
582- mi_stat_count_t pages_abandoned ; // abandonded pages count
583- mi_stat_count_t threads ; // number of threads
584- mi_stat_count_t malloc_normal ; // allocated bytes <= MI_LARGE_OBJ_SIZE_MAX
585- mi_stat_count_t malloc_huge ; // allocated bytes in huge pages
586- mi_stat_count_t malloc_requested ; // malloc requested bytes
587-
588- mi_stat_counter_t mmap_calls ;
589- mi_stat_counter_t commit_calls ;
590- mi_stat_counter_t reset_calls ;
591- mi_stat_counter_t purge_calls ;
592- mi_stat_counter_t arena_count ; // number of memory arena's
593- mi_stat_counter_t malloc_normal_count ; // number of blocks <= MI_LARGE_OBJ_SIZE_MAX
594- mi_stat_counter_t malloc_huge_count ; // number of huge bloks
595- mi_stat_counter_t malloc_guarded_count ; // number of allocations with guard pages
596-
597- // internal statistics
598- mi_stat_counter_t arena_rollback_count ;
599- mi_stat_counter_t pages_extended ; // number of page extensions
600- mi_stat_counter_t pages_retire ; // number of pages that are retired
601- mi_stat_counter_t page_searches ; // searches for a fresh page
602- // only on v1 and v2
603- mi_stat_count_t segments ;
604- mi_stat_count_t segments_abandoned ;
605- mi_stat_count_t segments_cache ;
606- mi_stat_count_t _segments_reserved ;
607- // only on v3
608- mi_stat_counter_t pages_reclaim_on_alloc ;
609- mi_stat_counter_t pages_reclaim_on_free ;
610- mi_stat_counter_t pages_reabandon_full ;
611- mi_stat_counter_t pages_unabandon_busy_wait ;
612-
613- // future extension
614- mi_stat_count_t _stat_reserved [4 ];
615- mi_stat_counter_t _stat_counter_reserved [4 ];
616-
617- // size segregated statistics
618- mi_stat_count_t malloc_bins [MI_BIN_HUGE + 1 ]; // allocation per size bin
619- mi_stat_count_t page_bins [MI_BIN_HUGE + 1 ]; // pages allocated per size bin
620- } mi_stats_t ;
621-
622-
623621// add to stat keeping track of the peak
624622void _mi_stat_increase (mi_stat_count_t * stat , size_t amount );
625623void _mi_stat_decrease (mi_stat_count_t * stat , size_t amount );
@@ -641,56 +639,4 @@ void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount);
641639#define mi_heap_stat_decrease (heap ,stat ,amount ) mi_stat_decrease( (heap)->tld->stats.stat, amount)
642640
643641
644- // ------------------------------------------------------
645- // Sub processes do not reclaim or visit segments
646- // from other sub processes
647- // ------------------------------------------------------
648-
649- struct mi_subproc_s {
650- _Atomic (size_t ) abandoned_count ; // count of abandoned segments for this sub-process
651- _Atomic (size_t ) abandoned_os_list_count ; // count of abandoned segments in the os-list
652- mi_lock_t abandoned_os_lock ; // lock for the abandoned os segment list (outside of arena's) (this lock protect list operations)
653- mi_lock_t abandoned_os_visit_lock ; // ensure only one thread per subproc visits the abandoned os list
654- mi_segment_t * abandoned_os_list ; // doubly-linked list of abandoned segments outside of arena's (in OS allocated memory)
655- mi_segment_t * abandoned_os_list_tail ; // the tail-end of the list
656- mi_memid_t memid ; // provenance of this memory block
657- };
658-
659- // ------------------------------------------------------
660- // Thread Local data
661- // ------------------------------------------------------
662-
663- // Milliseconds as in `int64_t` to avoid overflows
664- typedef int64_t mi_msecs_t ;
665-
666- // Queue of segments
667- typedef struct mi_segment_queue_s {
668- mi_segment_t * first ;
669- mi_segment_t * last ;
670- } mi_segment_queue_t ;
671-
672- // Segments thread local data
673- typedef struct mi_segments_tld_s {
674- mi_segment_queue_t small_free ; // queue of segments with free small pages
675- mi_segment_queue_t medium_free ; // queue of segments with free medium pages
676- mi_page_queue_t pages_purge ; // queue of freed pages that are delay purged
677- size_t count ; // current number of segments;
678- size_t peak_count ; // peak number of segments
679- size_t current_size ; // current size of all segments
680- size_t peak_size ; // peak size of all segments
681- size_t reclaim_count ;// number of reclaimed (abandoned) segments
682- mi_subproc_t * subproc ; // sub-process this thread belongs to.
683- mi_stats_t * stats ; // points to tld stats
684- } mi_segments_tld_t ;
685-
686- // Thread local data
687- struct mi_tld_s {
688- unsigned long long heartbeat ; // monotonic heartbeat count
689- bool recurse ; // true if deferred was called; used to prevent infinite recursion.
690- mi_heap_t * heap_backing ; // backing heap of this thread (cannot be deleted)
691- mi_heap_t * heaps ; // list of heaps in this thread (so we can abandon all when the thread terminates)
692- mi_segments_tld_t segments ; // segment tld
693- mi_stats_t stats ; // statistics
694- };
695-
696642#endif
0 commit comments