static void report_machine_readable()

in rts/Stats.c [869:1026]


static void report_machine_readable (const RTSSummaryStats * sum)
{
    // We should do no calculation, other than unit changes and formatting, and
    // we should not not use any data from outside of globals, sum and stats
    // here. See Note [RTS Stats Reporting]
    uint32_t g;

#define MR_STAT(field_name,format,value) \
    statsPrintf(" ,(\"" field_name "\", \"%" format "\")\n", value)
#define MR_STAT_GEN(gen,field_name,format,value) \
    statsPrintf(" ,(\"gen_%" FMT_Word32 "_" field_name "\", \"%" \
      format "\")\n", g, value)

    // These first values are for backwards compatibility.
    // Some of these first fields are duplicated with more machine-readable
    // names, or to match the name in RtsStats.

    // we don't use for the first field helper macro here because the prefix is
    // different
    statsPrintf(" [(\"%s\", \"%" FMT_Word64 "\")\n", "bytes allocated",
                stats.allocated_bytes);
    MR_STAT("num_GCs", FMT_Word32, stats.gcs);
    MR_STAT("average_bytes_used", FMT_Word64, sum->average_bytes_used);
    MR_STAT("max_bytes_used", FMT_Word64, stats.max_live_bytes);
    MR_STAT("num_byte_usage_samples", FMT_Word32, stats.major_gcs);
    MR_STAT("peak_megabytes_allocated", FMT_Word64,
      stats.max_mem_in_use_bytes / (1024 * 1024));

    MR_STAT("init_cpu_seconds", "f", TimeToSecondsDbl(stats.init_cpu_ns));
    MR_STAT("init_wall_seconds", "f", TimeToSecondsDbl(stats.init_elapsed_ns));
    MR_STAT("mut_cpu_seconds", "f", TimeToSecondsDbl(stats.mutator_cpu_ns));
    MR_STAT("mut_wall_seconds", "f",
            TimeToSecondsDbl(stats.mutator_elapsed_ns));
    MR_STAT("GC_cpu_seconds", "f", TimeToSecondsDbl(stats.gc_cpu_ns));
    MR_STAT("GC_wall_seconds", "f", TimeToSecondsDbl(stats.gc_elapsed_ns));

    // end backward compatibility

    // First, the rest of the times

    MR_STAT("exit_cpu_seconds", "f", TimeToSecondsDbl(sum->exit_cpu_ns));
    MR_STAT("exit_wall_seconds", "f", TimeToSecondsDbl(sum->exit_elapsed_ns));
#if defined(PROFILING)
    MR_STAT("rp_cpu_seconds", "f", TimeToSecondsDbl(sum->rp_cpu_ns));
    MR_STAT("rp_wall_seconds", "f", TimeToSecondsDbl(sum->rp_elapsed_ns));
    MR_STAT("hc_cpu_seconds", "f", TimeToSecondsDbl(sum->hc_cpu_ns));
    MR_STAT("hc_wall_seconds", "f", TimeToSecondsDbl(sum->hc_elapsed_ns));
#endif
    MR_STAT("total_cpu_seconds", "f", TimeToSecondsDbl(stats.cpu_ns));
    MR_STAT("total_wall_seconds", "f",
            TimeToSecondsDbl(stats.elapsed_ns));

    // next, the remainder of the fields of RTSStats, except internal counters

    // The first two are duplicates of those above, but have more machine
    // readable names that match the field names in RTSStats.


    // gcs has been done as num_GCs above
    MR_STAT("major_gcs", FMT_Word32, stats.major_gcs);
    MR_STAT("allocated_bytes", FMT_Word64, stats.allocated_bytes);
    MR_STAT("max_live_bytes", FMT_Word64, stats.max_live_bytes);
    MR_STAT("max_large_objects_bytes", FMT_Word64,
            stats.max_large_objects_bytes);
    MR_STAT("max_compact_bytes", FMT_Word64, stats.max_compact_bytes);
    MR_STAT("max_slop_bytes", FMT_Word64, stats.max_slop_bytes);
    // This duplicates, except for unit, peak_megabytes_allocated above
    MR_STAT("max_mem_in_use_bytes", FMT_Word64, stats.max_mem_in_use_bytes);
    MR_STAT("cumulative_live_bytes", FMT_Word64, stats.cumulative_live_bytes);
    MR_STAT("copied_bytes", FMT_Word64, stats.copied_bytes);
    MR_STAT("par_copied_bytes", FMT_Word64, stats.par_copied_bytes);
    MR_STAT("cumulative_par_max_copied_bytes", FMT_Word64,
            stats.cumulative_par_max_copied_bytes);
    MR_STAT("cumulative_par_balanced_copied_bytes", FMT_Word64,
            stats.cumulative_par_balanced_copied_bytes);

    // next, the computed fields in RTSSummaryStats
#if !defined(THREADED_RTS) // THREADED_RTS
    MR_STAT("gc_cpu_percent", "f", sum->gc_cpu_percent);
    MR_STAT("gc_wall_percent", "f", sum->gc_cpu_percent);
#endif
    MR_STAT("fragmentation_bytes", FMT_Word64, sum->fragmentation_bytes);
    // average_bytes_used is done above
    MR_STAT("alloc_rate", FMT_Word64, sum->alloc_rate);
    MR_STAT("productivity_cpu_percent", "f", sum->productivity_cpu_percent);
    MR_STAT("productivity_wall_percent", "f",
            sum->productivity_elapsed_percent);

    // next, the THREADED_RTS fields in RTSSummaryStats

#if defined(THREADED_RTS)
    MR_STAT("bound_task_count", FMT_Word32, sum->bound_task_count);
    MR_STAT("sparks_count", FMT_Word64, sum->sparks_count);
    MR_STAT("sparks_converted", FMT_Word, sum->sparks.converted);
    MR_STAT("sparks_overflowed", FMT_Word, sum->sparks.overflowed);
    MR_STAT("sparks_dud ", FMT_Word, sum->sparks.dud);
    MR_STAT("sparks_gcd", FMT_Word, sum->sparks.gcd);
    MR_STAT("sparks_fizzled", FMT_Word, sum->sparks.fizzled);
    MR_STAT("work_balance", "f", sum->work_balance);

    // next, globals (other than internal counters)
    MR_STAT("n_capabilities", FMT_Word32, n_capabilities);
    MR_STAT("task_count", FMT_Word32, taskCount);
    MR_STAT("peak_worker_count", FMT_Word32, peakWorkerCount);
    MR_STAT("worker_count", FMT_Word32, workerCount);

    // next, internal counters
#if defined(PROF_SPIN)
    MR_STAT("gc_alloc_block_sync_spin", FMT_Word64, gc_alloc_block_sync.spin);
    MR_STAT("gc_alloc_block_sync_yield", FMT_Word64,
            gc_alloc_block_sync.yield);
    MR_STAT("gc_alloc_block_sync_spin", FMT_Word64, gc_alloc_block_sync.spin);
    MR_STAT("gc_spin_spin", FMT_Word64, stats.gc_spin_spin);
    MR_STAT("gc_spin_yield", FMT_Word64, stats.gc_spin_yield);
    MR_STAT("mut_spin_spin", FMT_Word64, stats.mut_spin_spin);
    MR_STAT("mut_spin_yield", FMT_Word64, stats.mut_spin_yield);
    MR_STAT("waitForGcThreads_spin", FMT_Word64, waitForGcThreads_spin);
    MR_STAT("waitForGcThreads_yield", FMT_Word64,
            waitForGcThreads_yield);
    MR_STAT("whitehole_gc_spin", FMT_Word64, whitehole_gc_spin);
    MR_STAT("whitehole_lockClosure_spin", FMT_Word64,
            whitehole_lockClosure_spin);
    MR_STAT("whitehole_lockClosure_yield", FMT_Word64,
            whitehole_lockClosure_yield);
    MR_STAT("whitehole_executeMessage_spin", FMT_Word64,
            whitehole_executeMessage_spin);
    MR_STAT("whitehole_threadPaused_spin", FMT_Word64,
            whitehole_threadPaused_spin);
    MR_STAT("any_work", FMT_Word64,
            stats.any_work);
    MR_STAT("no_work", FMT_Word64,
            stats.no_work);
    MR_STAT("scav_find_work", FMT_Word64,
            stats.scav_find_work);
#endif // PROF_SPIN
#endif // THREADED_RTS

    // finally, per-generation stats. Named as, for example for generation 0,
    // gen_0_collections
    for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
        const GenerationSummaryStats* gc_sum = &sum->gc_summary_stats[g];
        MR_STAT_GEN(g, "collections", FMT_Word32, gc_sum->collections);
        MR_STAT_GEN(g, "par_collections", FMT_Word32, gc_sum->par_collections);
        MR_STAT_GEN(g, "cpu_seconds", "f", TimeToSecondsDbl(gc_sum->cpu_ns));
        MR_STAT_GEN(g, "wall_seconds", "f",
                    TimeToSecondsDbl(gc_sum->elapsed_ns));
        MR_STAT_GEN(g, "max_pause_seconds", "f",
                    TimeToSecondsDbl(gc_sum->max_pause_ns));
        MR_STAT_GEN(g, "avg_pause_seconds", "f",
                    TimeToSecondsDbl(gc_sum->avg_pause_ns));
#if defined(THREADED_RTS) && defined(PROF_SPIN)
        MR_STAT_GEN(g, "sync_spin", FMT_Word64, gc_sum->sync_spin);
        MR_STAT_GEN(g, "sync_yield", FMT_Word64, gc_sum->sync_yield);
#endif
    }

    statsPrintf(" ]\n");
}