huangcm
2024-12-18 9d29be7f7249789d6ffd0440067187a9f040c2cd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include "src/trace_processor/filtered_row_index.h"
 
#include <numeric>
 
namespace perfetto {
namespace trace_processor {
 
FilteredRowIndex::FilteredRowIndex(uint32_t start_row, uint32_t end_row)
    : mode_(Mode::kAllRows), start_row_(start_row), end_row_(end_row) {}
 
void FilteredRowIndex::IntersectRows(std::vector<uint32_t> rows) {
  PERFETTO_DCHECK(error_.empty());
 
  // Sort the rows so all branches below make sense.
  std::sort(rows.begin(), rows.end());
 
  if (mode_ == kAllRows) {
    mode_ = Mode::kRowVector;
    // Yes you're reading this code correctly. We use lower_bound in both cases.
    // Yes this is very intentional and has to do with |end_row_| already being
    // one greater than the value we are searching for so we need the first
    // iterator which is *geq* the |end_row_|.
    auto begin = std::lower_bound(rows.begin(), rows.end(), start_row_);
    auto end = std::lower_bound(begin, rows.end(), end_row_);
    rows_.insert(rows_.end(), begin, end);
    return;
  } else if (mode_ == kRowVector) {
    std::vector<uint32_t> intersected;
    std::set_intersection(rows_.begin(), rows_.end(), rows.begin(), rows.end(),
                          std::back_inserter(intersected));
    rows_ = std::move(intersected);
    return;
  }
 
  // Initialise start to the beginning of the vector.
  auto start = row_filter_.begin();
 
  // Skip directly to the rows in range of start and end.
  size_t i = 0;
  for (; i < rows.size() && rows[i] < start_row_; i++) {
  }
  for (; i < rows.size() && rows[i] < end_row_; i++) {
    // Unset all bits between the start iterator and the iterator pointing
    // to the current row. That is, this loop sets all elements not pointed
    // to by rows to false. It does not touch the rows themselves which
    // means if they were already false (i.e. not returned) then they won't
    // be returned now and if they were true (i.e. returned) they will still
    // be returned.
    auto row = rows[i];
    auto end = row_filter_.begin() + static_cast<ptrdiff_t>(row - start_row_);
    std::fill(start, end, false);
    start = end + 1;
  }
  std::fill(start, row_filter_.end(), false);
}
 
std::vector<uint32_t> FilteredRowIndex::ToRowVector() {
  PERFETTO_DCHECK(error_.empty());
 
  switch (mode_) {
    case Mode::kAllRows:
      mode_ = Mode::kRowVector;
      rows_.resize(end_row_ - start_row_);
      std::iota(rows_.begin(), rows_.end(), start_row_);
      break;
    case Mode::kBitVector:
      ConvertBitVectorToRowVector();
      break;
    case Mode::kRowVector:
      // Nothing to do.
      break;
  }
  return TakeRowVector();
}
 
void FilteredRowIndex::ConvertBitVectorToRowVector() {
  PERFETTO_DCHECK(error_.empty());
 
  mode_ = Mode::kRowVector;
 
  auto b = row_filter_.begin();
  auto e = row_filter_.end();
  using std::find;
  for (auto it = find(b, e, true); it != e; it = find(it + 1, e, true)) {
    auto filter_idx = static_cast<uint32_t>(std::distance(b, it));
    rows_.emplace_back(filter_idx + start_row_);
  }
  row_filter_.clear();
}
 
std::unique_ptr<RowIterator> FilteredRowIndex::ToRowIterator(bool desc) {
  PERFETTO_DCHECK(error_.empty());
 
  switch (mode_) {
    case Mode::kAllRows:
      return std::unique_ptr<RangeRowIterator>(
          new RangeRowIterator(start_row_, end_row_, desc));
    case Mode::kBitVector: {
      return std::unique_ptr<RangeRowIterator>(
          new RangeRowIterator(start_row_, desc, TakeBitVector()));
    }
    case Mode::kRowVector: {
      auto vector = TakeRowVector();
      if (desc)
        std::reverse(vector.begin(), vector.end());
      return std::unique_ptr<VectorRowIterator>(
          new VectorRowIterator(std::move(vector)));
    }
  }
  PERFETTO_FATAL("For GCC");
}
 
std::vector<uint32_t> FilteredRowIndex::TakeRowVector() {
  PERFETTO_DCHECK(error_.empty());
 
  PERFETTO_DCHECK(mode_ == Mode::kRowVector);
  auto vector = std::move(rows_);
  rows_.clear();
  mode_ = Mode::kAllRows;
  return vector;
}
 
std::vector<bool> FilteredRowIndex::TakeBitVector() {
  PERFETTO_DCHECK(error_.empty());
 
  PERFETTO_DCHECK(mode_ == Mode::kBitVector);
  auto filter = std::move(row_filter_);
  row_filter_.clear();
  mode_ = Mode::kAllRows;
  return filter;
}
 
}  // namespace trace_processor
}  // namespace perfetto