@@ -216,6 +216,10 @@ bool operator==(const Frame& lhs, const Frame& rhs) noexcept {
216
216
return lhs.frame == rhs.frame && lhs.line == rhs.line ;
217
217
}
218
218
219
+ bool operator !=(const Frame& lhs, const Frame& rhs) noexcept {
220
+ return !(lhs == rhs);
221
+ }
222
+
219
223
namespace std {
220
224
template <>
221
225
struct hash <Frame>
@@ -289,7 +293,9 @@ struct RawSample {
289
293
}
290
294
291
295
Frame frame (int i) const {
292
- const Frame frame = {frames[i], lines[i]};
296
+ int idx = len - i - 1 ;
297
+ if (idx < 0 ) throw std::out_of_range (" out of range" );
298
+ const Frame frame = {frames[idx], lines[idx]};
293
299
return frame;
294
300
}
295
301
@@ -408,27 +414,29 @@ struct FrameList {
408
414
}
409
415
410
416
StackNode *node = &root_stack_node;
411
- for (int i = stack.size () - 1 ; i >= 0 ; i-- ) {
412
- const Frame & frame = stack.frame (i);
417
+ for (int i = 0 ; i < stack.size (); i++ ) {
418
+ Frame frame = stack.frame (i);
413
419
node = next_stack_node (node, frame);
414
420
}
415
421
return node->index ;
416
422
}
417
423
418
- StackNode *next_stack_node (StackNode *node, const Frame & frame) {
419
- int next_node_idx = node->children [ frame] ;
420
- if (next_node_idx == 0 ) {
424
+ StackNode *next_stack_node (StackNode *node, Frame frame) {
425
+ auto search = node->children . find ( frame) ;
426
+ if (search == node-> children . end () ) {
421
427
// insert a new node
422
- next_node_idx = stack_node_list.size ();
428
+ int next_node_idx = stack_node_list.size ();
423
429
node->children [frame] = next_node_idx;
424
430
stack_node_list.emplace_back (
425
431
frame,
426
432
next_node_idx,
427
433
node->index
428
434
);
435
+ return &stack_node_list[next_node_idx];
436
+ } else {
437
+ int node_idx = search->second ;
438
+ return &stack_node_list[node_idx];
429
439
}
430
-
431
- return &stack_node_list[next_node_idx];
432
440
}
433
441
434
442
// Converts Frames from stacks other tables. "Symbolicates" the frames
@@ -508,6 +516,41 @@ struct FrameList {
508
516
}
509
517
};
510
518
519
+ class SampleTranslator {
520
+ public:
521
+ int last_stack_index;
522
+
523
+ Frame frames[RawSample::MAX_LEN];
524
+ int frame_indexes[RawSample::MAX_LEN];
525
+ int len;
526
+
527
+ SampleTranslator () : len(0 ), last_stack_index(-1 ) {
528
+ }
529
+
530
+ int translate (FrameList &frame_list, const RawSample &sample) {
531
+ int i = 0 ;
532
+ for (; i < len && i < sample.size (); i++) {
533
+ if (frames[i] != sample.frame (i)) {
534
+ break ;
535
+ }
536
+ }
537
+
538
+ FrameList::StackNode *node = i == 0 ? &frame_list.root_stack_node : &frame_list.stack_node_list [frame_indexes[i - 1 ]];
539
+
540
+ for (; i < sample.size (); i++) {
541
+ Frame frame = sample.frame (i);
542
+ node = frame_list.next_stack_node (node, frame);
543
+
544
+ frames[i] = frame;
545
+ frame_indexes[i] = node->index ;
546
+ }
547
+ len = i;
548
+
549
+ last_stack_index = node->index ;
550
+ return last_stack_index;
551
+ }
552
+ };
553
+
511
554
typedef uint64_t native_thread_id_t ;
512
555
static native_thread_id_t get_native_thread_id () {
513
556
#ifdef __APPLE__
@@ -691,6 +734,7 @@ class Thread {
691
734
TimeStamp stopped_at;
692
735
693
736
RawSample stack_on_suspend;
737
+ SampleTranslator translator;
694
738
695
739
std::string name;
696
740
@@ -1142,7 +1186,7 @@ class TimeCollector : public BaseCollector {
1142
1186
1143
1187
void record_sample (const RawSample &sample, TimeStamp time, Thread &thread, Category category) {
1144
1188
if (!sample.empty ()) {
1145
- int stack_index = frame_list. stack_index ( sample);
1189
+ int stack_index = thread. translator . translate (frame_list, sample);
1146
1190
thread.samples .record_sample (
1147
1191
stack_index,
1148
1192
time ,
@@ -1185,6 +1229,7 @@ class TimeCollector : public BaseCollector {
1185
1229
} else {
1186
1230
}
1187
1231
}
1232
+
1188
1233
threads.mutex .unlock ();
1189
1234
1190
1235
TimeStamp sample_complete = TimeStamp::Now ();
0 commit comments