• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #include "src/trace_processor/containers/row_map.h"
18 
19 namespace perfetto {
20 namespace trace_processor {
21 
22 namespace {
23 
SelectRangeWithRange(uint32_t start,uint32_t end,uint32_t selector_start,uint32_t selector_end)24 RowMap SelectRangeWithRange(uint32_t start,
25                             uint32_t end,
26                             uint32_t selector_start,
27                             uint32_t selector_end) {
28   PERFETTO_DCHECK(start <= end);
29   PERFETTO_DCHECK(selector_start <= selector_end);
30   PERFETTO_DCHECK(selector_end <= end - start);
31 
32   return RowMap(start + selector_start, start + selector_end);
33 }
34 
SelectRangeWithBv(uint32_t start,uint32_t end,const BitVector & selector)35 RowMap SelectRangeWithBv(uint32_t start,
36                          uint32_t end,
37                          const BitVector& selector) {
38   PERFETTO_DCHECK(start <= end);
39   PERFETTO_DCHECK(selector.size() <= end - start);
40 
41   // If |start| == 0 and |selector.size()| <= |end - start| (which is a
42   // precondition for this function), the BitVector we generate is going to be
43   // exactly |selector|.
44   //
45   // This is a fast path for the common situation where, post-filtering,
46   // SelectRows is called on all the table RowMaps with a BitVector. The self
47   // RowMap will always be a range so we expect this case to be hit at least
48   // once every filter operation.
49   if (start == 0u)
50     return RowMap(selector.Copy());
51 
52   // We only need to resize to |start| + |selector.size()| as we know any rows
53   // not covered by |selector| are going to be removed below.
54   BitVector bv(start, false);
55   bv.Resize(start + selector.size(), true);
56 
57   bv.UpdateSetBits(selector);
58   return RowMap(std::move(bv));
59 }
60 
SelectRangeWithIv(uint32_t start,uint32_t end,const std::vector<uint32_t> & selector)61 RowMap SelectRangeWithIv(uint32_t start,
62                          uint32_t end,
63                          const std::vector<uint32_t>& selector) {
64   PERFETTO_DCHECK(start <= end);
65 
66   std::vector<uint32_t> iv(selector.size());
67   for (uint32_t i = 0; i < selector.size(); ++i) {
68     PERFETTO_DCHECK(selector[i] < end - start);
69     iv[i] = selector[i] + start;
70   }
71   return RowMap(std::move(iv));
72 }
73 
SelectBvWithRange(const BitVector & bv,uint32_t selector_start,uint32_t selector_end)74 RowMap SelectBvWithRange(const BitVector& bv,
75                          uint32_t selector_start,
76                          uint32_t selector_end) {
77   PERFETTO_DCHECK(selector_start <= selector_end);
78   PERFETTO_DCHECK(selector_end <= bv.GetNumBitsSet());
79 
80   BitVector ret = bv.Copy();
81   for (auto it = ret.IterateSetBits(); it; it.Next()) {
82     auto set_idx = it.ordinal();
83     if (set_idx < selector_start || set_idx >= selector_end)
84       it.Clear();
85   }
86   return RowMap(std::move(ret));
87 }
88 
SelectBvWithBv(const BitVector & bv,const BitVector & selector)89 RowMap SelectBvWithBv(const BitVector& bv, const BitVector& selector) {
90   BitVector ret = bv.Copy();
91   ret.UpdateSetBits(selector);
92   return RowMap(std::move(ret));
93 }
94 
SelectBvWithIv(const BitVector & bv,const std::vector<uint32_t> & selector)95 RowMap SelectBvWithIv(const BitVector& bv,
96                       const std::vector<uint32_t>& selector) {
97   std::vector<uint32_t> iv(selector.size());
98   for (uint32_t i = 0; i < selector.size(); ++i) {
99     // TODO(lalitm): this is pretty inefficient.
100     iv[i] = bv.IndexOfNthSet(selector[i]);
101   }
102   return RowMap(std::move(iv));
103 }
104 
SelectIvWithRange(const std::vector<uint32_t> & iv,uint32_t selector_start,uint32_t selector_end)105 RowMap SelectIvWithRange(const std::vector<uint32_t>& iv,
106                          uint32_t selector_start,
107                          uint32_t selector_end) {
108   PERFETTO_DCHECK(selector_start <= selector_end);
109   PERFETTO_DCHECK(selector_end <= iv.size());
110 
111   std::vector<uint32_t> ret(selector_end - selector_start);
112   for (uint32_t i = selector_start; i < selector_end; ++i) {
113     ret[i - selector_start] = iv[i];
114   }
115   return RowMap(std::move(ret));
116 }
117 
SelectIvWithBv(const std::vector<uint32_t> & iv,const BitVector & selector)118 RowMap SelectIvWithBv(const std::vector<uint32_t>& iv,
119                       const BitVector& selector) {
120   PERFETTO_DCHECK(selector.size() <= iv.size());
121 
122   std::vector<uint32_t> copy = iv;
123   copy.resize(selector.size());
124 
125   uint32_t idx = 0;
126   auto it = std::remove_if(
127       copy.begin(), copy.end(),
128       [&idx, &selector](uint32_t) { return !selector.IsSet(idx++); });
129   copy.erase(it, copy.end());
130   return RowMap(std::move(copy));
131 }
132 
SelectIvWithIv(const std::vector<uint32_t> & iv,const std::vector<uint32_t> & selector)133 RowMap SelectIvWithIv(const std::vector<uint32_t>& iv,
134                       const std::vector<uint32_t>& selector) {
135   std::vector<uint32_t> ret(selector.size());
136   for (uint32_t i = 0; i < selector.size(); ++i) {
137     PERFETTO_DCHECK(selector[i] < iv.size());
138     ret[i] = iv[selector[i]];
139   }
140   return RowMap(std::move(ret));
141 }
142 
143 }  // namespace
144 
RowMap()145 RowMap::RowMap() : RowMap(0, 0) {}
146 
RowMap(uint32_t start,uint32_t end,OptimizeFor optimize_for)147 RowMap::RowMap(uint32_t start, uint32_t end, OptimizeFor optimize_for)
148     : mode_(Mode::kRange),
149       start_idx_(start),
150       end_idx_(end),
151       optimize_for_(optimize_for) {}
152 
RowMap(BitVector bit_vector)153 RowMap::RowMap(BitVector bit_vector)
154     : mode_(Mode::kBitVector), bit_vector_(std::move(bit_vector)) {}
155 
RowMap(std::vector<uint32_t> vec)156 RowMap::RowMap(std::vector<uint32_t> vec)
157     : mode_(Mode::kIndexVector), index_vector_(std::move(vec)) {}
158 
Copy() const159 RowMap RowMap::Copy() const {
160   switch (mode_) {
161     case Mode::kRange:
162       return RowMap(start_idx_, end_idx_);
163     case Mode::kBitVector:
164       return RowMap(bit_vector_.Copy());
165     case Mode::kIndexVector:
166       return RowMap(index_vector_);
167   }
168   PERFETTO_FATAL("For GCC");
169 }
170 
SelectRowsSlow(const RowMap & selector) const171 RowMap RowMap::SelectRowsSlow(const RowMap& selector) const {
172   // Pick the strategy based on the selector as there is more common code
173   // between selectors of the same mode than between the RowMaps being
174   // selected of the same mode.
175   switch (selector.mode_) {
176     case Mode::kRange:
177       switch (mode_) {
178         case Mode::kRange:
179           return SelectRangeWithRange(start_idx_, end_idx_, selector.start_idx_,
180                                       selector.end_idx_);
181         case Mode::kBitVector:
182           return SelectBvWithRange(bit_vector_, selector.start_idx_,
183                                    selector.end_idx_);
184         case Mode::kIndexVector:
185           return SelectIvWithRange(index_vector_, selector.start_idx_,
186                                    selector.end_idx_);
187       }
188       break;
189     case Mode::kBitVector:
190       switch (mode_) {
191         case Mode::kRange:
192           return SelectRangeWithBv(start_idx_, end_idx_, selector.bit_vector_);
193         case Mode::kBitVector:
194           return SelectBvWithBv(bit_vector_, selector.bit_vector_);
195         case Mode::kIndexVector:
196           return SelectIvWithBv(index_vector_, selector.bit_vector_);
197       }
198       break;
199     case Mode::kIndexVector:
200       switch (mode_) {
201         case Mode::kRange:
202           return SelectRangeWithIv(start_idx_, end_idx_,
203                                    selector.index_vector_);
204         case Mode::kBitVector:
205           return SelectBvWithIv(bit_vector_, selector.index_vector_);
206         case Mode::kIndexVector:
207           return SelectIvWithIv(index_vector_, selector.index_vector_);
208       }
209       break;
210   }
211   PERFETTO_FATAL("For GCC");
212 }
213 
214 }  // namespace trace_processor
215 }  // namespace perfetto
216