Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
stacktrace.cpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
16
18#include "shambase/time.hpp"
19#include <sstream>
20#include <string>
21#include <vector>
22
23namespace shambase::details {
24
27 std::string name;
29 bool is_start;
30
36 std::string format(u32 world_rank);
37 };
38
39 std::string ChromeProfileEntry::format(u32 world_rank) {
40 if (is_start) {
41 return shambase::format_printf(
42 R"({
43 "cat": "%s",
44 "pid": %d,
45 "tid": %d,
46 "ts": %zu,
47 "ph": "B",
48 "name": "%s",
49 "args": {
50 }
51 })",
52 name.c_str(),
53 world_rank,
54 world_rank,
56 name.c_str());
57
58 } else {
59 return shambase::format_printf(
60 R"({
61 "cat": "%s",
62 "pid": %d,
63 "tid": %d,
64 "ts": %zu,
65 "ph": "E",
66 "name": "%s",
67 "args": {
68 }
69 })",
70 name.c_str(),
71 world_rank,
72 world_rank,
74 name.c_str());
75 }
76 }
77
79 std::vector<ChromeProfileEntry> profile_data_chrome;
80
86 * @param is_start Whether the entry is a start or end entry
87 */
88 inline void add_entry_chrome(std::source_location loc, f64 time, bool is_start) {
89 // Convert time to microseconds
90 auto to_prof_time = [](f64 in) {
91 return static_cast<u64>(in * 1e6);
92 };
93 // Add the entry to the storage
94 profile_data_chrome.push_back(
96 .name = loc.function_name(), .time_val = to_prof_time(time), .is_start = is_start});
97 }
98
102 inline void clear_chrome_entry() { profile_data_chrome.clear(); }
103
104 void dump_profilings_chrome(const std::string &process_prefix, u32 world_rank) {
105
106 // Open the file for writing
107 std::ofstream outfile(process_prefix + std::to_string(world_rank));
108 // Write the start of the JSON array
109 outfile << "[";
110
111 // Write each entry
112 u32 len = profile_data_chrome.size();
113
114 for (u32 i = 0; i < len; i++) {
115 // Write the entry in the JSON format
116 outfile << profile_data_chrome[i].format(world_rank);
117 // Add a comma if it's not the last entry
118 if (i != len - 1) {
119 outfile << ",";
120 }
121 }
122
123 // Write the end of the JSON array
124 outfile << "]";
125 // Close the file
126 outfile.close();
127 }
128
129} // namespace shambase::details
130
131namespace shambase::details {
132
134 auto make_timer = []() -> Timer {
135 Timer tmp;
136 tmp.start();
137 return tmp;
138 };
139
142
143 // two entry types,
144 // one with start, end
145 // one with start, end as separate envents
146
157 std::string entry_name;
158
164 std::string format() {
165 return shambase::format_printf(
166 R"({"tstart": %f, "tend": %f, "name": "%s"})", time_start, time_end, entry_name);
167 }
168 };
169
173 std::vector<ProfileEntry> profile_data;
174
181 global_timer.stop();
182 return global_timer.elapsed_sec();
183 }
184
185 void register_profile_entry_start(std::source_location loc, f64 start_time) {
186 add_entry_chrome(loc, start_time, true);
187 };
188
189 void register_profile_entry(std::source_location loc, f64 start_time, f64 end_time) {
190 // Add the profile entry to the storage
191 profile_data.push_back(
192 {.time_start = start_time, .time_end = end_time, .entry_name = loc.function_name()});
193 // Add a Chrome profiling entry to the storage
194 add_entry_chrome(loc, end_time, false);
195 };
196
198 profile_data.clear();
200 }
201
202 void dump_profilings(const std::string &process_prefix, u32 world_rank) {
203 std::ofstream outfile(process_prefix + std::to_string(world_rank));
204 outfile << "[";
205
206 u32 len = profile_data.size();
207
208 for (u32 i = 0; i < len; i++) {
209 outfile << profile_data[i].format();
210 if (i != len - 1) {
211 outfile << ",";
212 }
213 }
214
215 outfile << "]";
216 outfile.close();
217 }
218
219} // namespace shambase::details
220
221namespace shambase {
222
223 std::string _callstack_process_identifier;
224
225 void set_callstack_process_identifier(std::string identifier) {
226 _callstack_process_identifier = std::move(identifier);
227 }
228
229 std::vector<std::function<std::string()>> _callstack_gen_info_generators;
230
231 void add_callstack_gen_info_generator(std::string (*generator)()) {
232 _callstack_gen_info_generators.push_back(std::move(generator));
233 }
234
240 std::string fmt_callstack() {
241 std::stack<SourceLocation> cpy = details::call_stack;
242
243 std::vector<std::string> lines;
244
245 while (!cpy.empty()) {
246 SourceLocation l = cpy.top();
247 lines.push_back(l.format_one_line_func());
248 cpy.pop();
249 }
250
251 std::reverse(lines.begin(), lines.end());
252
253 std::stringstream ss;
254
255 if (!_callstack_process_identifier.empty()) {
256 ss << " -> process identifier: " << _callstack_process_identifier << "\n";
257 }
258
259 for (u32 i = 0; i < lines.size(); i++) {
260 ss << shambase::format(" {:2} : {}\n", i, lines[i]);
261 }
262
263 for (auto &generator : _callstack_gen_info_generators) {
264 ss << generator() << "\n";
265 }
266
267 return ss.str();
268 }
269
270} // namespace shambase
double f64
Alias for double.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
Class Timer measures the time elapsed since the timer was started.
Definition time.hpp:35
void start()
Starts the timer.
Definition time.hpp:50
namespace for basic c++ utilities
std::string fmt_callstack()
Get the formatted callstack.
void add_entry_chrome(std::source_location loc, f64 time, bool is_start)
Add a Chrome tracing entry to the storage.
auto make_timer
Utility to create a timer and start it.
Timer global_timer
Wall time global timer.
void clear_chrome_entry()
Clear the Chrome tracing entries storage.
std::vector< ChromeProfileEntry > profile_data_chrome
Chrome tracing entries storage.
std::vector< ProfileEntry > profile_data
Vector to hold profiling entries.
This file contains the definition for the stacktrace related functionality.
std::stack< SourceLocation > call_stack
The call stack used to keep track of the stack trace. It is used to print the stack trace when an exc...
void register_profile_entry(std::source_location loc, f64 start_time, f64 end_time)
Register a profile entry. This register the end of a profile entry for chrome tracing and a complete ...
void dump_profilings(const std::string &process_prefix, u32 world_rank)
Dump the profiling data in a JSON format to a file.
void register_profile_entry_start(std::source_location loc, f64 start_time)
Register the start of a profile entry. This is required for chrome profiling as there is a separate e...
f64 get_wtime()
Returns the current wall clock time in seconds.
void clear_profiling_data()
Clear the profiling data. (should be done in large run to avoid out-of-memory).
provide information about the source location
std::string format_one_line_func() const
format the location in a one liner with the function name displayed
Chrome tracing profile entry.
u64 time_val
Time value for the profile entry.
std::string name
Name of the profile entry.
bool is_start
Flag indicating if it is the start of the profile entry.
std::string format(u32 world_rank)
Format the Chrome profile entry.
Structure to hold data for a profiling entry.
f64 time_start
Start time of the profiling entry (in sec since program start).
std::string entry_name
Name of the profiling entry.
std::string format()
Format the profile entry as a JSON string.
f64 time_end
End time of the profiling entry (in sec since program start).