@@ -22,44 +22,67 @@ int main() {
2222 auto profile = Profile::create ({wall_time}, period);
2323 std::cout << " ✅ Profile created" << std::endl;
2424
25- // Add samples
25+ // Add samples with realistic stack traces
2626 std::cout << " Adding samples..." << std::endl;
2727 for (int i = 0 ; i < 100 ; i++) {
28- // Create mapping
29- CxxMapping mapping{
30- 0x10000000 , // memory_start
31- 0x20000000 , // memory_limit
32- 0 , // file_offset
33- " /usr/lib/libexample.so" , // filename
34- " abc123def456" // build_id
35- };
28+ // Keep dynamically generated strings alive for the duration of add_sample()
29+ // The profile will intern them, so they can be freed after that call
30+ std::vector<std::string> string_storage;
31+
32+ CxxMapping mapping{0x10000000 , 0x20000000 , 0 , " /usr/lib/libexample.so" , " abc123" };
3633
37- // Create function
38- auto func_name = " my_function_" + std::to_string (i % 10 );
39- auto sys_name = " _Z11my_function" + std::to_string (i % 10 ) + " v" ;
40- CxxFunction function{func_name.c_str (), sys_name.c_str (), " /path/to/source.cpp" };
34+ // Leaf frame - where the CPU was actually spending time
35+ string_storage.push_back (" hot_function_" + std::to_string (i % 3 ));
36+ string_storage.push_back (" _Z12hot_function" + std::to_string (i % 3 ) + " v" );
37+ CxxFunction leaf_func{string_storage[0 ].c_str (), string_storage[1 ].c_str (), " /src/hot_path.cpp" };
38+ CxxLocation leaf_frame{
39+ mapping, leaf_func,
40+ static_cast <uint64_t >(0x10003000 + (i % 3 ) * 0x100 ),
41+ 100 + (i % 3 ) * 10
42+ };
4143
42- // Create location
43- CxxLocation location{
44- mapping,
45- function,
46- static_cast <uint64_t >(0x12345678 + i * 0x100 ), // address
47- 42 + i // line
44+ // Middle frame - intermediate call
45+ string_storage.push_back (" process_request_" + std::to_string (i % 5 ));
46+ string_storage.push_back (" _Z15process_request" + std::to_string (i % 5 ) + " v" );
47+ CxxFunction mid_func{string_storage[2 ].c_str (), string_storage[3 ].c_str (), " /src/handler.cpp" };
48+ CxxLocation mid_frame{
49+ mapping, mid_func,
50+ static_cast <uint64_t >(0x10002000 + (i % 5 ) * 0x80 ),
51+ 50 + (i % 5 ) * 5
4852 };
4953
54+ // Root frame - entry point
55+ CxxFunction root_func{" main" , " main" , " /src/main.cpp" };
56+ CxxLocation root_frame{mapping, root_func, 0x10001000 , 42 };
57+
5058 // Create labels
5159 CxxLabel thread_label{" thread_id" , " " , static_cast <int64_t >(i % 4 ), " " };
52- CxxLabel counter_label{" unique_counter " , " " , static_cast <int64_t >(i), " " };
60+ CxxLabel counter_label{" sample_id " , " " , static_cast <int64_t >(i), " " };
5361
54- // Create sample using initializer lists
55- int64_t wall_time_value = 1000000 ; // 1ms
56- CxxSample sample{
57- {location}, // locations
58- {wall_time_value}, // values
59- {thread_label, counter_label} // labels
60- };
62+ // Create sample with stack trace (3-4 frames depending on sample)
63+ int64_t wall_time_value = 1000000 + (i % 1000 ) * 1000 ; // 1-2ms
6164
62- profile->add_sample (sample);
65+ if (i % 7 == 0 ) {
66+ // Deeper stack (4 frames)
67+ CxxFunction worker_func{" worker_loop" , " _Z11worker_loopv" , " /src/worker.cpp" };
68+ CxxLocation worker_frame{mapping, worker_func, 0x10000500 , 25 };
69+
70+ CxxSample sample{
71+ {leaf_frame, mid_frame, root_frame, worker_frame}, // 4-frame stack
72+ {wall_time_value},
73+ {thread_label, counter_label}
74+ };
75+ profile->add_sample (sample);
76+ } else {
77+ // Normal stack (3 frames)
78+ CxxSample sample{
79+ {leaf_frame, mid_frame, root_frame}, // 3-frame stack
80+ {wall_time_value},
81+ {thread_label, counter_label}
82+ };
83+ profile->add_sample (sample);
84+ }
85+ // string_storage vector destroyed here, but profile has already interned the strings
6386 }
6487
6588 std::cout << " ✅ Added 100 samples" << std::endl;
0 commit comments