]> git.llucax.com Git - software/dgc/cdgc.git/blobdiff - rt/gc/cdgc/stats.d
Add (optional) early collection support
[software/dgc/cdgc.git] / rt / gc / cdgc / stats.d
index 314b50950cd3e4c5def35d9fdb4189638b19a1bb..b854812eab740a31cfe5cd1a498dd883a6b9aba2 100644 (file)
@@ -123,6 +123,8 @@ struct MallocInfo
     double timestamp = -1.0;
     /// Time spent in the malloc() call (in seconds).
     double time = -1.0;
+    /// Address of the pointer returned by malloc.
+    void* ptr = null;
     /// Memory requested by the malloc() call (in bytes).
     size_t size = 0;
     /// Memory attributes as BlkAttr flags.
@@ -155,7 +157,7 @@ struct Stats
 private:
 
     /// The GC instance we are collecting stats from.
-    .gc.GC gc = null;
+    .gc.GC* gc = null;
 
     /// True if statistics should be collected.
     bool active = false;
@@ -186,13 +188,13 @@ private:
     /// Fill a MemoryInfo struct with the current state of the GC heap.
     void fill_memory_info(MemoryInfo* mem_info)
     {
-        mem_info.overhead += .gc.GC.classinfo.init.length + .gc.Gcx.sizeof
-                + .gc.pools.size_of + .gc.roots.size_of + .gc.ranges.size_of;
+        mem_info.overhead += .gc.GC.sizeof + gc.pools.elements_sizeof +
+                gc.roots.elements_sizeof + gc.ranges.elements_sizeof;
 
         // pools
-        for (size_t i = 0; i < .gc.pools.length; i++)
+        for (size_t i = 0; i < gc.pools.length; i++)
         {
-            auto pool = .gc.pools[i];
+            auto pool = gc.pools[i];
             mem_info.overhead += pool.npages * ubyte.sizeof;
             // the 5 bitmaps (mark, scan, free, final, noscan)
             mem_info.overhead += 5 * (GCBits.sizeof
@@ -226,8 +228,8 @@ private:
     cstdio.FILE* start_file(char* filename, char* header)
     {
         cstdio.FILE* file = cstdio.fopen(filename, "w");
-        assert (file !is null);
-        cstdio.fputs(header, file);
+        if (file !is null)
+            cstdio.fputs(header, file);
         return file;
     }
 
@@ -235,17 +237,25 @@ private:
     {
         if (this.mallocs_file is null)
             return;
+        auto ptrmap = this.malloc_info.ptrmap;
+        auto ptrmask_offset = (ptrmap[0] - 1) / (size_t.sizeof * 8) + 1;
         cstdio.fprintf(this.mallocs_file,
-                "%f,%f,%zu,%zu,%zu,%zu,%zu,%p\n",
-                //0  1   2   3   4   5   6  7
+                "%f,%f,%p,%zu,%zu,%zu,%zu,%zu,%p,%zu,%0*zX,%0*zX\n",
+                //0  1   2   3   4   5   6  7  8   9    10    11
                 this.malloc_info.timestamp,                   // 0
                 this.malloc_info.time,                        // 1
-                this.malloc_info.size,                        // 2
-                this.malloc_info.collected ? 1u : 0u,         // 3
-                this.malloc_info.attr & .gc.BlkAttr.FINALIZE, // 4
-                this.malloc_info.attr & .gc.BlkAttr.NO_SCAN,  // 5
-                this.malloc_info.attr & .gc.BlkAttr.NO_MOVE,  // 6
-                this.malloc_info.ptrmap);                     // 7
+                this.malloc_info.ptr,                         // 2
+                this.malloc_info.size,                        // 3
+                this.malloc_info.collected ? 1u : 0u,         // 4
+                this.malloc_info.attr & .gc.BlkAttr.FINALIZE, // 5
+                this.malloc_info.attr & .gc.BlkAttr.NO_SCAN,  // 6
+                this.malloc_info.attr & .gc.BlkAttr.NO_MOVE,  // 7
+                ptrmap,                                       // 8
+                ptrmap[0] * size_t.sizeof,                    // 9
+                size_t.sizeof,                                // fill length
+                ptrmap[1],                                    // 10
+                size_t.sizeof,                                // fill length
+                ptrmap[1 + ptrmask_offset]);                  // 11
         // TODO: make it an option
         cstdio.fflush(this.mallocs_file);
     }
@@ -283,25 +293,29 @@ public:
      * the program start time (in seconds since the epoch) needs to be taken to
      * properly add timestamps to allocations and collections.
      */
-    static Stats opCall(.gc.GC gc)
+    static Stats opCall(.gc.GC* gc)
     {
         Stats this_;
         this_.gc = gc;
         if (options.malloc_stats_file[0] != '\0') {
-            this_.active = true;
             this_.mallocs_file = this_.start_file(
                     options.malloc_stats_file.ptr,
-                    "Timestamp,Time,Size,Collection triggered,"
-                    "Finalize,No scan,No move,Pointer map\n");
+                    "Timestamp,Time,Pointer,Size,Collection triggered,"
+                    "Finalize,No scan,No move,Pointer map,Type size,"
+                    "Pointer map scan bitmask (first word, hexa),"
+                    "Pointer map pointer bitmask (first word, hexa)\n");
+            if (this_.mallocs_file !is null)
+                this_.active = true;
         }
         // collection
         if (options.collect_stats_file[0] != '\0') {
-            this_.active = true;
             this_.collections_file = this_.start_file(
                     options.collect_stats_file.ptr,
                     "Timestamp,Malloc time,Collection time,Stop-the-world time,"
                     "Used before,Free before,Wasted before,Overhead before,"
                     "Used after,Free after,Wasted after,Overhead after\n");
+            if (this_.collections_file !is null)
+                this_.active = true;
         }
         this_.program_start = this_.now();
         return this_;
@@ -338,7 +352,7 @@ public:
     }
 
     /// Inform the end of an allocation.
-    void malloc_finished()
+    void malloc_finished(void* ptr)
     {
         if (!this.active)
             return;
@@ -348,6 +362,7 @@ public:
         this.malloc_info.time = now - this.malloc_info.time;
         if (collected)
             this.malloc_info.collected = true;
+        this.malloc_info.ptr = ptr;
         this.print_malloc();
         if (!collected)
             return;