Remove a outdated comment [skip ci]
[ghc.git] / rts / ProfilerReportJson.c
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 1998-2017
4 *
5 * Generating cost-centre profiler JSON report
6 *
7 * ---------------------------------------------------------------------------*/
8
9 #if defined(PROFILING)
10
11 #include "PosixSource.h"
12 #include "Rts.h"
13
14 #include "RtsUtils.h"
15 #include "ProfilerReportJson.h"
16 #include "Profiling.h"
17
18 // This only handles characters that you might see in a Haskell cost-centre
19 // name.
20 static void escapeString(char const* str, char *out, int len)
21 {
22 len--; // reserve character in output for terminating NUL
23 for (; *str != '\0' && len > 0; str++) {
24 char c = *str;
25 if (c == '\\') {
26 if (len < 2) break;
27 *out = '\\'; out++; len--;
28 *out = '\\'; out++; len--;
29 } else if (c == '\n') {
30 if (len < 2) break;
31 *out = '\\'; out++; len--;
32 *out = 'n'; out++; len--;
33 } else {
34 *out = c; out++; len--;
35 }
36 }
37 *out = '\0';
38 }
39
40 static void
41 logCostCentres(FILE *prof_file)
42 {
43 char tmp[256];
44 bool needs_comma = false;
45 fprintf(prof_file, "[\n");
46 for (CostCentre *cc = CC_LIST; cc != NULL; cc = cc->link) {
47 escapeString(cc->label, tmp, sizeof(tmp));
48 fprintf(prof_file,
49 "%s"
50 "{\"id\": %" FMT_Int ", "
51 "\"label\": \"%s\", "
52 "\"module\": \"%s\", "
53 "\"src_loc\": \"%s\", "
54 "\"is_caf\": %s}",
55 needs_comma ? ", " : "",
56 cc->ccID, tmp, cc->module, cc->srcloc,
57 cc->is_caf ? "true" : "false");
58 needs_comma = true;
59 }
60 fprintf(prof_file, "]\n");
61 }
62
63 static void
64 logCostCentreStack(FILE *prof_file, CostCentreStack const *ccs)
65 {
66 fprintf(prof_file,
67 "{\"id\": %" FMT_Int ", "
68 "\"entries\": %" FMT_Word64 ", "
69 "\"alloc\": %" FMT_Word ", "
70 "\"ticks\": %" FMT_Word ", ",
71 ccs->cc->ccID,
72 ccs->scc_count,
73 ccs->mem_alloc * sizeof(W_),
74 ccs->time_ticks);
75
76 bool need_comma = false;
77 fprintf(prof_file, "\"children\": [");
78 for (IndexTable *i = ccs->indexTable; i != 0; i = i->next) {
79 if (!i->back_edge) {
80 if (need_comma) {
81 fprintf(prof_file, ",");
82 }
83 logCostCentreStack(prof_file, i->ccs);
84 need_comma = true;
85 }
86 }
87 fprintf(prof_file, "]}\n");
88 }
89
90 void
91 writeCCSReportJson(FILE *prof_file,
92 CostCentreStack const *stack,
93 ProfilerTotals totals)
94 {
95 fprintf(prof_file, "{\n\"program\": \"%s\",\n", prog_name);
96 fprintf(prof_file, "\"arguments\": [");
97 for (int count = 0; prog_argv[count]; count++)
98 fprintf(prof_file, "%s\"%s\"",
99 count == 0 ? "" : ", ", prog_argv[count]);
100 fprintf(prof_file, "],\n\"rts_arguments\": [");
101 for (int count = 0; rts_argv[count]; count++)
102 fprintf(prof_file, "%s\"%s\"",
103 count == 0 ? "" : ", ", rts_argv[count]);
104 fprintf(prof_file, "],\n");
105
106 fprintf(prof_file, "\"end_time\": \"%s\",\n", time_str());
107 fprintf(prof_file, "\"initial_capabilities\": %d,\n",
108 RtsFlags.ParFlags.nCapabilities);
109 fprintf(prof_file, "\"total_time\": %11.2f,\n",
110 ((double) totals.total_prof_ticks *
111 (double) RtsFlags.MiscFlags.tickInterval) / (TIME_RESOLUTION * n_capabilities));
112 fprintf(prof_file, "\"total_ticks\": %lu,\n",
113 (unsigned long) totals.total_prof_ticks);
114 fprintf(prof_file, "\"tick_interval\": %d,\n",
115 (int) TimeToUS(RtsFlags.MiscFlags.tickInterval));
116 fprintf(prof_file, "\"total_alloc\":%" FMT_Word64 ",\n",
117 totals.total_alloc * sizeof(W_));
118
119 fprintf(prof_file, "\"cost_centres\": ");
120 logCostCentres(prof_file);
121 fprintf(prof_file, ",\n\"profile\": ");
122 logCostCentreStack(prof_file, stack);
123 fprintf(prof_file, "}\n");
124 }
125
126
127 #endif /* PROFILING */