Skip to content

Commit a2660a7

Browse files
committed
Cache common frames between samples
This also fixes a bug where we would generate duplicate a duplicate stack for the 0 index.
1 parent bcbe007 commit a2660a7

File tree

1 file changed

+55
-10
lines changed

1 file changed

+55
-10
lines changed

ext/vernier/vernier.cc

+55-10
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ bool operator==(const Frame& lhs, const Frame& rhs) noexcept {
216216
return lhs.frame == rhs.frame && lhs.line == rhs.line;
217217
}
218218

219+
bool operator!=(const Frame& lhs, const Frame& rhs) noexcept {
220+
return !(lhs == rhs);
221+
}
222+
219223
namespace std {
220224
template<>
221225
struct hash<Frame>
@@ -289,7 +293,9 @@ struct RawSample {
289293
}
290294

291295
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]};
293299
return frame;
294300
}
295301

@@ -408,27 +414,29 @@ struct FrameList {
408414
}
409415

410416
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);
413419
node = next_stack_node(node, frame);
414420
}
415421
return node->index;
416422
}
417423

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()) {
421427
// insert a new node
422-
next_node_idx = stack_node_list.size();
428+
int next_node_idx = stack_node_list.size();
423429
node->children[frame] = next_node_idx;
424430
stack_node_list.emplace_back(
425431
frame,
426432
next_node_idx,
427433
node->index
428434
);
435+
return &stack_node_list[next_node_idx];
436+
} else {
437+
int node_idx = search->second;
438+
return &stack_node_list[node_idx];
429439
}
430-
431-
return &stack_node_list[next_node_idx];
432440
}
433441

434442
// Converts Frames from stacks other tables. "Symbolicates" the frames
@@ -508,6 +516,41 @@ struct FrameList {
508516
}
509517
};
510518

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+
511554
typedef uint64_t native_thread_id_t;
512555
static native_thread_id_t get_native_thread_id() {
513556
#ifdef __APPLE__
@@ -691,6 +734,7 @@ class Thread {
691734
TimeStamp stopped_at;
692735

693736
RawSample stack_on_suspend;
737+
SampleTranslator translator;
694738

695739
std::string name;
696740

@@ -1142,7 +1186,7 @@ class TimeCollector : public BaseCollector {
11421186

11431187
void record_sample(const RawSample &sample, TimeStamp time, Thread &thread, Category category) {
11441188
if (!sample.empty()) {
1145-
int stack_index = frame_list.stack_index(sample);
1189+
int stack_index = thread.translator.translate(frame_list, sample);
11461190
thread.samples.record_sample(
11471191
stack_index,
11481192
time,
@@ -1185,6 +1229,7 @@ class TimeCollector : public BaseCollector {
11851229
} else {
11861230
}
11871231
}
1232+
11881233
threads.mutex.unlock();
11891234

11901235
TimeStamp sample_complete = TimeStamp::Now();

0 commit comments

Comments
 (0)