1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef SIMPLE_PERF_SAMPLE_COMPARATOR_H_
18 #define SIMPLE_PERF_SAMPLE_COMPARATOR_H_
19
20 #include <string.h>
21
22 #include <vector>
23
24 namespace simpleperf {
25
26 // The compare functions below are used to compare two samples by their item
27 // content.
28
29 template <typename T>
Compare(const T & a,const T & b)30 int Compare(const T& a, const T& b) {
31 if (a != b) {
32 return a < b ? -1 : 1;
33 }
34 return 0;
35 }
36
37 #define BUILD_COMPARE_VALUE_FUNCTION(function_name, compare_part) \
38 template <typename EntryT> \
39 int function_name(const EntryT* sample1, const EntryT* sample2) { \
40 return Compare(sample1->compare_part, sample2->compare_part); \
41 }
42
43 #define BUILD_COMPARE_VALUE_FUNCTION_REVERSE(function_name, compare_part) \
44 template <typename EntryT> \
45 int function_name(const EntryT* sample1, const EntryT* sample2) { \
46 return Compare(sample2->compare_part, sample1->compare_part); \
47 }
48
49 #define BUILD_COMPARE_STRING_FUNCTION(function_name, compare_part) \
50 template <typename EntryT> \
51 int function_name(const EntryT* sample1, const EntryT* sample2) { \
52 return strcmp(sample1->compare_part, sample2->compare_part); \
53 }
54
55 BUILD_COMPARE_VALUE_FUNCTION(ComparePid, pid);
56 BUILD_COMPARE_VALUE_FUNCTION(CompareTid, tid);
57 BUILD_COMPARE_VALUE_FUNCTION_REVERSE(CompareSampleCount, sample_count);
58 BUILD_COMPARE_STRING_FUNCTION(CompareComm, thread_comm);
59 BUILD_COMPARE_STRING_FUNCTION(CompareDso, map->dso->GetReportPath().data());
60 BUILD_COMPARE_STRING_FUNCTION(CompareSymbol, symbol->DemangledName());
61 BUILD_COMPARE_STRING_FUNCTION(CompareDsoFrom, branch_from.map->dso->GetReportPath().data());
62 BUILD_COMPARE_STRING_FUNCTION(CompareSymbolFrom, branch_from.symbol->DemangledName());
63 BUILD_COMPARE_VALUE_FUNCTION(CompareCallGraphDuplicated, callchain.duplicated);
64
65 template <typename EntryT>
CompareTotalPeriod(const EntryT * sample1,const EntryT * sample2)66 int CompareTotalPeriod(const EntryT* sample1, const EntryT* sample2) {
67 uint64_t period1 = sample1->period + sample1->accumulated_period;
68 uint64_t period2 = sample2->period + sample2->accumulated_period;
69 return Compare(period2, period1);
70 }
71
72 template <typename EntryT>
ComparePeriod(const EntryT * sample1,const EntryT * sample2)73 int ComparePeriod(const EntryT* sample1, const EntryT* sample2) {
74 return Compare(sample2->period, sample1->period);
75 }
76
77 // SampleComparator is a class using a collection of compare functions to
78 // compare two samples.
79
80 template <typename EntryT>
81 class SampleComparator {
82 public:
83 typedef int (*compare_sample_func_t)(const EntryT*, const EntryT*);
84
AddCompareFunction(compare_sample_func_t func)85 void AddCompareFunction(compare_sample_func_t func) { compare_v_.push_back(func); }
86
AddComparator(const SampleComparator<EntryT> & other)87 void AddComparator(const SampleComparator<EntryT>& other) {
88 compare_v_.insert(compare_v_.end(), other.compare_v_.begin(), other.compare_v_.end());
89 }
90
operator()91 bool operator()(const EntryT* sample1, const EntryT* sample2) const {
92 for (const auto& func : compare_v_) {
93 int ret = func(sample1, sample2);
94 if (ret != 0) {
95 return ret < 0;
96 }
97 }
98 return false;
99 }
100
operator()101 bool operator()(const EntryT& sample1, const EntryT& sample2) const {
102 for (const auto& func : compare_v_) {
103 int ret = func(&sample1, &sample2);
104 if (ret != 0) {
105 return ret < 0;
106 }
107 }
108 return false;
109 }
110
IsSameSample(const EntryT * sample1,const EntryT * sample2)111 bool IsSameSample(const EntryT* sample1, const EntryT* sample2) const {
112 for (const auto& func : compare_v_) {
113 if (func(sample1, sample2) != 0) {
114 return false;
115 }
116 }
117 return true;
118 }
119
empty()120 bool empty() const { return compare_v_.empty(); }
121
122 private:
123 std::vector<compare_sample_func_t> compare_v_;
124 };
125
126 } // namespace simpleperf
127
128 #endif // SIMPLE_PERF_SAMPLE_COMPARATOR_H_
129