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