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 // The compare functions below are used to compare two samples by their item
25 // content.
26 
27 template <typename T>
Compare(const T & a,const T & b)28 int Compare(const T& a, const T& b) {
29   if (a != b) {
30     return a < b ? -1 : 1;
31   }
32   return 0;
33 }
34 
35 #define BUILD_COMPARE_VALUE_FUNCTION(function_name, compare_part)   \
36   template <typename EntryT>                                        \
37   int function_name(const EntryT* sample1, const EntryT* sample2) { \
38     return Compare(sample1->compare_part, sample2->compare_part);   \
39   }
40 
41 #define BUILD_COMPARE_VALUE_FUNCTION_REVERSE(function_name, compare_part) \
42   template <typename EntryT>                                              \
43   int function_name(const EntryT* sample1, const EntryT* sample2) {       \
44     return Compare(sample2->compare_part, sample1->compare_part);         \
45   }
46 
47 #define BUILD_COMPARE_STRING_FUNCTION(function_name, compare_part)  \
48   template <typename EntryT>                                        \
49   int function_name(const EntryT* sample1, const EntryT* sample2) { \
50     return strcmp(sample1->compare_part, sample2->compare_part);    \
51   }
52 
53 BUILD_COMPARE_VALUE_FUNCTION(ComparePid, thread->pid);
54 BUILD_COMPARE_VALUE_FUNCTION(CompareTid, thread->tid);
55 BUILD_COMPARE_VALUE_FUNCTION_REVERSE(CompareSampleCount, sample_count);
56 BUILD_COMPARE_STRING_FUNCTION(CompareComm, thread_comm);
57 BUILD_COMPARE_STRING_FUNCTION(CompareDso, map->dso->Path().c_str());
58 BUILD_COMPARE_STRING_FUNCTION(CompareSymbol, symbol->DemangledName());
59 BUILD_COMPARE_STRING_FUNCTION(CompareDsoFrom,
60                               branch_from.map->dso->Path().c_str());
61 BUILD_COMPARE_STRING_FUNCTION(CompareSymbolFrom,
62                               branch_from.symbol->DemangledName());
63 
64 template <typename EntryT>
CompareTotalPeriod(const EntryT * sample1,const EntryT * sample2)65 int CompareTotalPeriod(const EntryT* sample1, const EntryT* sample2) {
66   uint64_t period1 = sample1->period + sample1->accumulated_period;
67   uint64_t period2 = sample2->period + sample2->accumulated_period;
68   return Compare(period2, period1);
69 }
70 
71 // SampleComparator is a class using a collection of compare functions to
72 // compare two samples.
73 
74 template <typename EntryT>
75 class SampleComparator {
76  public:
77   typedef int (*compare_sample_func_t)(const EntryT*, const EntryT*);
78 
AddCompareFunction(compare_sample_func_t func)79   void AddCompareFunction(compare_sample_func_t func) {
80     compare_v_.push_back(func);
81   }
82 
AddComparator(const SampleComparator<EntryT> & other)83   void AddComparator(const SampleComparator<EntryT>& other) {
84     compare_v_.insert(compare_v_.end(), other.compare_v_.begin(),
85                       other.compare_v_.end());
86   }
87 
operator()88   bool operator()(const EntryT* sample1, const EntryT* sample2) const {
89     for (const auto& func : compare_v_) {
90       int ret = func(sample1, sample2);
91       if (ret != 0) {
92         return ret < 0;
93       }
94     }
95     return false;
96   }
97 
IsSameSample(const EntryT * sample1,const EntryT * sample2)98   bool IsSameSample(const EntryT* sample1, const EntryT* sample2) const {
99     for (const auto& func : compare_v_) {
100       if (func(sample1, sample2) != 0) {
101         return false;
102       }
103     }
104     return true;
105   }
106 
empty()107   bool empty() const { return compare_v_.empty(); }
108 
109  private:
110   std::vector<compare_sample_func_t> compare_v_;
111 };
112 
113 #endif  // SIMPLE_PERF_SAMPLE_COMPARATOR_H_
114