hoshi-lang dev
Yet another programming language
Loading...
Searching...
No Matches
hperf.cpp
Go to the documentation of this file.
1//
2// Created by XIaokang00010 on 2026/1/1.
3//
4
6#include <cstdio>
7#include <cstring>
9
11
12bool hperf_enabled = false;
13
15
17 // use malloc to allocate the context, so that we don't need to worry about memory management
18 HPerfContext *ctx = static_cast<HPerfContext *>(malloc(sizeof(HPerfContext)));
19 ctx->unique_id = unique_id;
20 ctx->pages = nullptr;
21 ctx->current_page = nullptr;
22 ctx->num_events = 0;
23 ctx->prev = nullptr;
24 ctx->next = hperf_contexts;
25 if (hperf_contexts != nullptr) {
26 hperf_contexts->prev = ctx;
27 }
28 hperf_contexts = ctx;
29 return ctx;
30}
31
33 // free all pages in the context
34 HPerfPage *page = ctx->pages;
35 while (page != nullptr) {
36 HPerfPage *next = page->next;
37 free(page);
38 page = next;
39 }
40 // remove the context from the list
41 if (ctx->next != nullptr) {
42 ctx->next->prev = ctx->prev;
43 }
44 if (ctx->prev != nullptr) {
45 ctx->prev->next = ctx->next;
46 } else {
47 hperf_contexts = ctx->next;
48 }
49 free(ctx);
50}
51
53 if (ctx->current_page == nullptr || ctx->current_page->num_events == 1024) {
54 // allocate a new page if the current one is full
55 auto page = static_cast<HPerfPage *>(calloc(sizeof(HPerfPage), 1));
56 page->next = nullptr;
57 if (ctx->current_page != nullptr) {
58 ctx->current_page->next = page;
59 } else {
60 ctx->pages = page;
61 }
62 ctx->current_page = page;
63 }
64 HPerfEvent *event = &ctx->current_page->data[ctx->current_page->num_events++];
65 ctx->num_events++;
66 struct timespec ts{};
67 clock_gettime(CLOCK_REALTIME, &ts);
68 event->timestamp.sec = ts.tv_sec;
69 event->timestamp.nsec = ts.tv_nsec;
70 return event;
71}
72
73void hperf_report_func_enter(const char *func_name) {
75 if (ctx == nullptr) {
76 return;
77 }
78 auto event = hperf_context_add_event(ctx);
80 auto data = reinterpret_cast<HPerfEventFuncEnter *>(event->data);
81 data->func_name = func_name;
82}
83
84void hperf_report_func_leave(const char *func_name) {
86 if (ctx == nullptr) {
87 return;
88 }
89 auto event = hperf_context_add_event(ctx);
91 auto data = reinterpret_cast<HPerfEventFuncLeave *>(event->data);
92 data->func_name = func_name;
93}
94
95void hperf_report_mem_alloc(void *ptr, size_t size) {
97 if (ctx == nullptr) {
98 return;
99 }
100 auto event = hperf_context_add_event(ctx);
102 auto data = reinterpret_cast<HPerfEventMemAlloc *>(event->data);
103 data->ptr = ptr;
104 data->size = size;
105}
106
107void hperf_report_mem_free(void *ptr) {
109 if (ctx == nullptr) {
110 return;
111 }
112 auto event = hperf_context_add_event(ctx);
114 auto data = reinterpret_cast<HPerfEventMemFree *>(event->data);
115 data->ptr = ptr;
116}
117
118void hperf_write_report(const char *filename) {
119 for (HPerfContext *ctx = hperf_contexts; ctx != nullptr; ctx = ctx->next) {
120 char real_filename[2048];
121 snprintf(real_filename, 2048, "%s.%lu.hperf.json", filename, ctx->unique_id);
122 FILE *f = fopen(real_filename, "w");
123 if (f == nullptr) {
124 return;
125 }
126 // we use json
127 fprintf(f,
128 R"({"filetype": "hperf-report", "version": 1, "unique-id": %lu, "num-events": %lu, "events": [)",
129 ctx->unique_id,
130 ctx->num_events);
131 bool first = true;
132 for (HPerfContext *c = hperf_contexts; c != nullptr; c = c->next) {
133 for (HPerfPage *p = c->pages; p != nullptr; p = p->next) {
134 for (size_t i = 0; i < p->num_events; i++) {
135 auto event = &p->data[i];
136 if (first) {
137 first = false;
138 } else {
139 fprintf(f, ",");
140 }
141 switch (event->type) {
143 auto data = reinterpret_cast<HPerfEventFuncEnter *>(event->data);
144 fprintf(
145 f,
146 R"({"type": "func-enter", "timestamp": {"sec": %llu, "nsec": %llu}, "func-name": "%s"})",
147 event->timestamp.sec,
148 event->timestamp.nsec,
149 data->func_name);
150 break;
151 }
153 auto data = reinterpret_cast<HPerfEventFuncLeave *>(event->data);
154 fprintf(
155 f,
156 R"({"type": "func-leave", "timestamp": {"sec": %llu, "nsec": %llu}, "func-name": "%s"})",
157 event->timestamp.sec,
158 event->timestamp.nsec,
159 data->func_name);
160 break;
161 }
163 auto data = reinterpret_cast<HPerfEventMemAlloc *>(event->data);
164 fprintf(
165 f,
166 R"({"type": "mem-alloc", "timestamp": {"sec": %llu, "nsec": %llu}, "ptr": %zu, "size": %lu})",
167 event->timestamp.sec,
168 event->timestamp.nsec,
169 (size_t)data->ptr,
170 data->size);
171 break;
172 }
174 auto data = reinterpret_cast<HPerfEventMemFree *>(event->data);
175 fprintf(f,
176 R"({"type": "mem-free", "timestamp": {"sec": %llu, "nsec": %llu}, "ptr": %zu})",
177 event->timestamp.sec,
178 event->timestamp.nsec,
179 (size_t)(data->ptr));
180 break;
181 }
182 }
183 }
184 }
185 }
186 fprintf(f, "]}\n");
187 fclose(f);
188 }
189}
190
191HPerfContext *hperf_context_get(size_t unique_id) {
193 while (ctx != nullptr) {
194 if (ctx->unique_id == unique_id) {
195 return ctx;
196 }
197 ctx = ctx->next;
198 }
199 return nullptr;
200}
201
202void hperf_init(const char *filename) {
203 hperf_enabled = true;
204 strcpy(hperf_report_filename, filename);
205 if (hperf_contexts == nullptr) {
207 }
208}
HPerfContext * hperf_context_create(size_t unique_id)
Definition hperf.cpp:16
HPerfContext * hperf_context_get(size_t unique_id)
Definition hperf.cpp:191
void hperf_context_finalize(HPerfContext *ctx)
Definition hperf.cpp:32
char hperf_report_filename[2048]
Definition hperf.cpp:14
void hperf_report_func_leave(const char *func_name)
Definition hperf.cpp:84
HPerfContext * hperf_contexts
Definition hperf.cpp:10
bool hperf_enabled
Definition hperf.cpp:12
void hperf_report_mem_free(void *ptr)
Definition hperf.cpp:107
void hperf_write_report(const char *filename)
Definition hperf.cpp:118
HPerfEvent * hperf_context_add_event(HPerfContext *ctx)
Definition hperf.cpp:52
void hperf_init(const char *filename)
Definition hperf.cpp:202
void hperf_report_mem_alloc(void *ptr, size_t size)
Definition hperf.cpp:95
void hperf_report_func_enter(const char *func_name)
Definition hperf.cpp:73
HPerfContext * prev
Definition hperf.h:57
HPerfPage * current_page
Definition hperf.h:61
HPerfContext * next
Definition hperf.h:58
size_t unique_id
Definition hperf.h:59
size_t num_events
Definition hperf.h:62
HPerfPage * pages
Definition hperf.h:60
const char * func_name
Definition hperf.h:34
const char * func_name
Definition hperf.h:38
HPerfPage * next
Definition hperf.h:53
HPerfEvent data[1024]
Definition hperf.h:51
size_t num_events
Definition hperf.h:52
uint64_t runtime_get_thread_id()