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;
/// 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
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;
}
{
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,%p,%zu,%zu,%zu,%zu,%zu,%p\n",
- //0 1 2 3 4 5 6 7 8
+ "%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.ptr, // 2
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
- this.malloc_info.ptrmap); // 8
+ 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);
}
* 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,Pointer,Size,Collection triggered,"
- "Finalize,No scan,No move,Pointer map\n");
+ "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_;