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"
20#include <fstream>
21#include <sstream>
22#include <string>
23#include <vector>
24
25namespace shambase::details {
26
29 std::string name;
31 bool is_start;
32
38 std::string format(u32 world_rank);
39 };
40
41 std::string ChromeProfileEntry::format(u32 world_rank) {
42 if (is_start) {
43 return sham::format_printf(
44 R"({
45 "cat": "%s",
46 "pid": %d,
47 "tid": %d,
48 "ts": %zu,
49 "ph": "B",
50 "name": "%s",
51 "args": {
52 }
53 })",
54 name.c_str(),
55 world_rank,
56 world_rank,
58 name.c_str());
59
60 } else {
61 return sham::format_printf(
62 R"({
63 "cat": "%s",
64 "pid": %d,
65 "tid": %d,
66 "ts": %zu,
67 "ph": "E",
68 "name": "%s",
69 "args": {
70 }
71 })",
72 name.c_str(),
73 world_rank,
74 world_rank,
76 name.c_str());
77 }
78 }
79
81 std::vector<ChromeProfileEntry> profile_data_chrome;
82
88 * @param is_start Whether the entry is a start or end entry
89 */
90 inline void add_entry_chrome(std::source_location loc, f64 time, bool is_start) {
91 // Convert time to microseconds
92 auto to_prof_time = [](f64 in) {
93 return static_cast<u64>(in * 1e6);
94 };
95 // Add the entry to the storage
96 profile_data_chrome.push_back(
98 .name = loc.function_name(), .time_val = to_prof_time(time), .is_start = is_start});
99 }
100
104 inline void clear_chrome_entry() { profile_data_chrome.clear(); }
105
106 void dump_profilings_chrome(const std::string &process_prefix, u32 world_rank) {
107
108 // Open the file for writing
109 std::ofstream outfile(process_prefix + std::to_string(world_rank));
110 // Write the start of the JSON array
111 outfile << "[";
112
113 // Write each entry
114 u32 len = profile_data_chrome.size();
115
116 for (u32 i = 0; i < len; i++) {
117 // Write the entry in the JSON format
118 outfile << profile_data_chrome[i].format(world_rank);
119 // Add a comma if it's not the last entry
120 if (i != len - 1) {
121 outfile << ",";
122 }
123 }
124
125 // Write the end of the JSON array
126 outfile << "]";
127 // Close the file
128 outfile.close();
129 }
130
131} // namespace shambase::details
132
133namespace shambase::details {
134
136 auto make_timer = []() -> Timer {
137 Timer tmp;
138 tmp.start();
139 return tmp;
140 };
141
144
145 // two entry types,
146 // one with start, end
147 // one with start, end as separate envents
148
159 std::string entry_name;
160
166 std::string format() {
167 return sham::format_printf(
168 R"({"tstart": %f, "tend": %f, "name": "%s"})", time_start, time_end, entry_name);
169 }
170 };
171
175 std::vector<ProfileEntry> profile_data;
176
183 global_timer.stop();
184 return global_timer.elapsed_sec();
185 }
186
187 void register_profile_entry_start(std::source_location loc, f64 start_time) {
188 add_entry_chrome(loc, start_time, true);
189 };
190
191 void register_profile_entry(std::source_location loc, f64 start_time, f64 end_time) {
192 // Add the profile entry to the storage
193 profile_data.push_back(
194 {.time_start = start_time, .time_end = end_time, .entry_name = loc.function_name()});
195 // Add a Chrome profiling entry to the storage
196 add_entry_chrome(loc, end_time, false);
197 };
198
200 profile_data.clear();
202 }
203
204 void dump_profilings(const std::string &process_prefix, u32 world_rank) {
205 std::ofstream outfile(process_prefix + std::to_string(world_rank));
206 outfile << "[";
207
208 u32 len = profile_data.size();
209
210 for (u32 i = 0; i < len; i++) {
211 outfile << profile_data[i].format();
212 if (i != len - 1) {
213 outfile << ",";
214 }
215 }
216
217 outfile << "]";
218 outfile.close();
219 }
220
221} // namespace shambase::details
222
223namespace shambase {
224
225 std::string _callstack_process_identifier;
226
227 void set_callstack_process_identifier(std::string identifier) {
228 _callstack_process_identifier = std::move(identifier);
229 }
230
231 std::vector<std::function<std::string()>> _callstack_gen_info_generators;
232
233 void add_callstack_gen_info_generator(std::string (*generator)()) {
234 _callstack_gen_info_generators.push_back(std::move(generator));
235 }
236
242 std::string fmt_callstack() {
243 std::stack<SourceLocation> cpy = details::call_stack;
244
245 std::vector<std::string> lines;
246
247 while (!cpy.empty()) {
248 SourceLocation l = cpy.top();
249 lines.push_back(l.format_one_line_func());
250 cpy.pop();
251 }
252
253 std::reverse(lines.begin(), lines.end());
254
255 std::stringstream ss;
256
257 if (!_callstack_process_identifier.empty()) {
258 ss << " -> process identifier: " << _callstack_process_identifier << "\n";
259 }
260
261 for (u32 i = 0; i < lines.size(); i++) {
262 ss << sham::format(" {:2} : {}\n", i, lines[i]);
263 }
264
265 for (auto &generator : _callstack_gen_info_generators) {
266 ss << generator() << "\n";
267 }
268
269 return ss.str();
270 }
271
272} // 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 Timer.hpp:36
void start()
Starts the timer.
Definition Timer.hpp:51
Core formatting functions: format, vformat, and format_printf.
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).