Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1194)

Side by Side Diff: courgette/label_manager.cc

Issue 1853943002: [Courgette] Refactor LabelManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "courgette/label_manager.h" 5 #include "courgette/label_manager.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/numerics/safe_conversions.h" 13 #include "base/numerics/safe_conversions.h"
14 #include "base/numerics/safe_math.h" 14 #include "base/numerics/safe_math.h"
15 #include "courgette/consecutive_range_visitor.h" 15 #include "courgette/consecutive_range_visitor.h"
16 16
17 namespace courgette { 17 namespace courgette {
18 18
19 LabelManager::LabelManager() {} 19 LabelManager::SimpleIndexAssigner::SimpleIndexAssigner(LabelVector* labels)
20
21 LabelManager::~LabelManager() {}
22
23 // static
24 int LabelManager::GetIndexBound(const LabelVector& labels) {
25 int max_index = -1;
26 for (const Label& label : labels) {
27 if (label.index_ != Label::kNoIndex)
28 max_index = std::max(max_index, label.index_);
29 }
30 return max_index + 1;
31 }
32
33 // static
34 int LabelManager::GetIndexBound(const RVAToLabel& labels_map) {
35 int max_index = -1;
36 for (const auto& rva_and_label : labels_map) {
37 const Label& label = *rva_and_label.second;
38 if (label.index_ != Label::kNoIndex)
39 max_index = std::max(max_index, label.index_);
40 }
41 return max_index + 1;
42 }
43
44 LabelManagerImpl::RvaVisitor::~RvaVisitor() {}
45
46 LabelManagerImpl::SimpleIndexAssigner::SimpleIndexAssigner(LabelVector* labels)
47 : labels_(labels) { 20 : labels_(labels) {
48 // Initialize |num_index_| and |available_|. 21 // Initialize |num_index_| and |available_|.
49 num_index_ = std::max(base::checked_cast<int>(labels_->size()), 22 num_index_ = std::max(base::checked_cast<int>(labels_->size()),
50 LabelManager::GetIndexBound(*labels_)); 23 GetLabelIndexBound(*labels_));
51 available_.resize(num_index_, true); 24 available_.resize(num_index_, true);
52 size_t used = 0; 25 size_t used = 0;
53 for (const Label& label : *labels_) { 26 for (const Label& label : *labels_) {
54 if (label.index_ != Label::kNoIndex) { 27 if (label.index_ != Label::kNoIndex) {
55 available_.at(label.index_) = false; 28 available_.at(label.index_) = false;
56 ++used; 29 ++used;
57 } 30 }
58 } 31 }
59 VLOG(1) << used << " of " << labels_->size() << " labels pre-assigned."; 32 VLOG(1) << used << " of " << labels_->size() << " labels pre-assigned.";
60 } 33 }
61 34
62 LabelManagerImpl::SimpleIndexAssigner::~SimpleIndexAssigner() {} 35 LabelManager::SimpleIndexAssigner::~SimpleIndexAssigner() {}
63 36
64 void LabelManagerImpl::SimpleIndexAssigner::DoForwardFill() { 37 void LabelManager::SimpleIndexAssigner::DoForwardFill() {
65 size_t count = 0; 38 size_t count = 0;
66 // Inside the loop, if |prev_index| == |kNoIndex| then we try to assign 0. 39 // Inside the loop, if |prev_index| == |kNoIndex| then we try to assign 0.
67 // This allows 0 (if unused) to be assigned in middle of |labels_|. 40 // This allows 0 (if unused) to be assigned in middle of |labels_|.
68 int prev_index = Label::kNoIndex; 41 int prev_index = Label::kNoIndex;
69 for (auto p = labels_->begin(); p != labels_->end(); ++p) { 42 for (auto p = labels_->begin(); p != labels_->end(); ++p) {
70 if (p->index_ == Label::kNoIndex) { 43 if (p->index_ == Label::kNoIndex) {
71 int index = (prev_index == Label::kNoIndex) ? 0 : prev_index + 1; 44 int index = (prev_index == Label::kNoIndex) ? 0 : prev_index + 1;
72 if (index < num_index_ && available_.at(index)) { 45 if (index < num_index_ && available_.at(index)) {
73 p->index_ = index; 46 p->index_ = index;
74 available_.at(index) = false; 47 available_.at(index) = false;
75 ++count; 48 ++count;
76 } 49 }
77 } 50 }
78 prev_index = p->index_; 51 prev_index = p->index_;
79 } 52 }
80 VLOG(1) << " fill forward " << count; 53 VLOG(1) << " fill forward " << count;
81 } 54 }
82 55
83 void LabelManagerImpl::SimpleIndexAssigner::DoBackwardFill() { 56 void LabelManager::SimpleIndexAssigner::DoBackwardFill() {
84 size_t count = 0; 57 size_t count = 0;
85 // This is asymmetric from DoForwardFill(), to preserve old behavior. 58 // This is asymmetric from DoForwardFill(), to preserve old behavior.
86 // Inside the loop, if |prev_index| == |kNoIndex| then we skip assignment. 59 // Inside the loop, if |prev_index| == |kNoIndex| then we skip assignment.
87 // But we initilaize |prev_index| = |num_index_|, so if the last element in 60 // But we initilaize |prev_index| = |num_index_|, so if the last element in
88 // |labels_| has no index, then can use |num_index_| - 1 (if unused). We don't 61 // |labels_| has no index, then can use |num_index_| - 1 (if unused). We don't
89 // try this assignment elsewhere. 62 // try this assignment elsewhere.
90 int prev_index = num_index_; 63 int prev_index = num_index_;
91 for (auto p = labels_->rbegin(); p != labels_->rend(); ++p) { 64 for (auto p = labels_->rbegin(); p != labels_->rend(); ++p) {
92 if (p->index_ == Label::kNoIndex && prev_index != Label::kNoIndex) { 65 if (p->index_ == Label::kNoIndex && prev_index != Label::kNoIndex) {
93 int index = prev_index - 1; 66 int index = prev_index - 1;
94 if (index >= 0 && available_.at(index)) { 67 if (index >= 0 && available_.at(index)) {
95 p->index_ = index; 68 p->index_ = index;
96 available_.at(index) = false; 69 available_.at(index) = false;
97 ++count; 70 ++count;
98 } 71 }
99 } 72 }
100 prev_index = p->index_; 73 prev_index = p->index_;
101 } 74 }
102 VLOG(1) << " fill backward " << count; 75 VLOG(1) << " fill backward " << count;
103 } 76 }
104 77
105 void LabelManagerImpl::SimpleIndexAssigner::DoInFill() { 78 void LabelManager::SimpleIndexAssigner::DoInFill() {
106 size_t count = 0; 79 size_t count = 0;
107 int index = 0; 80 int index = 0;
108 for (Label& label : *labels_) { 81 for (Label& label : *labels_) {
109 if (label.index_ == Label::kNoIndex) { 82 if (label.index_ == Label::kNoIndex) {
110 while (!available_.at(index)) 83 while (!available_.at(index))
111 ++index; 84 ++index;
112 label.index_ = index; 85 label.index_ = index;
113 available_.at(index) = false; 86 available_.at(index) = false;
114 ++index; 87 ++index;
115 ++count; 88 ++count;
116 } 89 }
117 } 90 }
118 VLOG(1) << " infill " << count; 91 VLOG(1) << " infill " << count;
119 } 92 }
120 93
121 LabelManagerImpl::LabelManagerImpl() {} 94 LabelManager::LabelManager() {}
122 95
123 LabelManagerImpl::~LabelManagerImpl() {} 96 LabelManager::~LabelManager() {}
124 97
125 // We wish to minimize peak memory usage here. Analysis: Let 98 // static
126 // m = number of (RVA) elements in |rva_visitor|, 99 int LabelManager::GetIndexBound(const RVAToLabel& labels_map) {
127 // n = number of distinct (RVA) elements in |rva_visitor|. 100 int max_index = -1;
128 // The final storage is n * sizeof(Label) bytes. During computation we uniquify 101 for (const auto& rva_and_label : labels_map) {
129 // m RVAs, and count repeats. Taking sizeof(RVA) = 4, an implementation using 102 const Label& label = *rva_and_label.second;
130 // std::map or std::unordered_map would consume additionally 32 * n bytes. 103 if (label.index_ != Label::kNoIndex)
131 // Meanwhile, our std::vector implementation consumes additionally 4 * m bytes 104 max_index = std::max(max_index, label.index_);
132 // For our typical usage (i.e. Chrome) we see m = ~4n, so we use 16 * n bytes of
133 // extra contiguous memory during computation. Assuming memory fragmentation
134 // would not be an issue, this is much better than using std::map.
135 void LabelManagerImpl::Read(RvaVisitor* rva_visitor) {
136 // Write all values in |rva_visitor| to |rvas|.
137 size_t num_rva = rva_visitor->Remaining();
138 std::vector<RVA> rvas(num_rva);
139 for (size_t i = 0; i < num_rva; ++i, rva_visitor->Next())
140 rvas[i] = rva_visitor->Get();
141
142 // Sort |rvas|, then count the number of distinct values.
143 using CRV = ConsecutiveRangeVisitor<std::vector<RVA>::iterator>;
144 std::sort(rvas.begin(), rvas.end());
145 DCHECK(rvas.empty() || rvas.back() != kUnassignedRVA);
146
147 size_t num_distinct_rva = 0;
148 for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance())
149 ++num_distinct_rva;
150
151 // Reserve space for |labels_|, populate with sorted RVA and repeats.
152 DCHECK(labels_.empty());
153 labels_.reserve(num_distinct_rva);
154 for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance()) {
155 labels_.push_back(Label(*it.cur()));
156 base::CheckedNumeric<uint32_t> count = it.repeat();
157 labels_.back().count_ = count.ValueOrDie();
158 } 105 }
106 return max_index + 1;
159 } 107 }
160 108
161 size_t LabelManagerImpl::Size() const { 109 // static
162 return labels_.size(); 110 int LabelManager::GetLabelIndexBound(const LabelVector& labels) {
111 int max_index = -1;
112 for (const Label& label : labels) {
113 if (label.index_ != Label::kNoIndex)
114 max_index = std::max(max_index, label.index_);
115 }
116 return max_index + 1;
163 } 117 }
164 118
165 // Uses binary search to find |rva|. 119 // Uses binary search to find |rva|.
166 Label* LabelManagerImpl::Find(RVA rva) { 120 Label* LabelManager::Find(RVA rva) {
167 auto it = std::lower_bound( 121 auto it = std::lower_bound(
168 labels_.begin(), labels_.end(), Label(rva), 122 labels_.begin(), labels_.end(), Label(rva),
169 [](const Label& l1, const Label& l2) { return l1.rva_ < l2.rva_; }); 123 [](const Label& l1, const Label& l2) { return l1.rva_ < l2.rva_; });
170 return it == labels_.end() || it->rva_ != rva ? nullptr : &(*it); 124 return it == labels_.end() || it->rva_ != rva ? nullptr : &(*it);
171 } 125 }
172 126
173 void LabelManagerImpl::RemoveUnderusedLabels(int32_t count_threshold) { 127 void LabelManager::RemoveUnderusedLabels(int32_t count_threshold) {
174 if (count_threshold <= 0) 128 if (count_threshold <= 0)
175 return; 129 return;
176 labels_.erase(std::remove_if(labels_.begin(), labels_.end(), 130 labels_.erase(std::remove_if(labels_.begin(), labels_.end(),
177 [count_threshold](const Label& label) { 131 [count_threshold](const Label& label) {
178 return label.count_ < count_threshold; 132 return label.count_ < count_threshold;
179 }), 133 }),
180 labels_.end()); 134 labels_.end());
181 // Not shrinking |labels_|, since this may cause reallocation. 135 // Not shrinking |labels_|, since this may cause reallocation.
182 } 136 }
183 137
184 void LabelManagerImpl::UnassignIndexes() { 138 void LabelManager::UnassignIndexes() {
185 for (Label& label : labels_) 139 for (Label& label : labels_)
186 label.index_ = Label::kNoIndex; 140 label.index_ = Label::kNoIndex;
187 } 141 }
188 142
189 void LabelManagerImpl::DefaultAssignIndexes() { 143 void LabelManager::DefaultAssignIndexes() {
190 int cur_index = 0; 144 int cur_index = 0;
191 for (Label& label : labels_) { 145 for (Label& label : labels_) {
192 CHECK_EQ(Label::kNoIndex, label.index_); 146 CHECK_EQ(Label::kNoIndex, label.index_);
193 label.index_ = cur_index++; 147 label.index_ = cur_index++;
194 } 148 }
195 } 149 }
196 150
197 void LabelManagerImpl::AssignRemainingIndexes() { 151 void LabelManager::AssignRemainingIndexes() {
198 // This adds some memory overhead, about 1 bit per Label (more if indexes >= 152 // This adds some memory overhead, about 1 bit per Label (more if indexes >=
199 // |labels_.size()| get used). 153 // |labels_.size()| get used).
200 SimpleIndexAssigner assigner(&labels_); 154 SimpleIndexAssigner assigner(&labels_);
201 assigner.DoForwardFill(); 155 assigner.DoForwardFill();
202 assigner.DoBackwardFill(); 156 assigner.DoBackwardFill();
203 assigner.DoInFill(); 157 assigner.DoInFill();
204 } 158 }
205 159
206 void LabelManagerImpl::SetLabels(const LabelVector& labels) { 160 // We wish to minimize peak memory usage here. Analysis: Let
207 labels_ = labels; 161 // m = number of (RVA) elements in |rva_visitor|,
162 // n = number of distinct (RVA) elements in |rva_visitor|.
163 // The final storage is n * sizeof(Label) bytes. During computation we uniquify
164 // m RVAs, and count repeats. Taking sizeof(RVA) = 4, an implementation using
165 // std::map or std::unordered_map would consume additionally 32 * n bytes.
166 // Meanwhile, our std::vector implementation consumes additionally 4 * m bytes
167 // For our typical usage (i.e. Chrome) we see m = ~4n, so we use 16 * n bytes of
168 // extra contiguous memory during computation. Assuming memory fragmentation
169 // would not be an issue, this is much better than using std::map.
170 void LabelManager::Read(RvaVisitor* rva_visitor) {
171 // Write all values in |rva_visitor| to |rvas|.
172 size_t num_rva = rva_visitor->Remaining();
173 std::vector<RVA> rvas(num_rva);
174 for (size_t i = 0; i < num_rva; ++i, rva_visitor->Next())
175 rvas[i] = rva_visitor->Get();
176
177 // Sort |rvas|, then count the number of distinct values.
178 using CRV = ConsecutiveRangeVisitor<std::vector<RVA>::iterator>;
179 std::sort(rvas.begin(), rvas.end());
180 DCHECK(rvas.empty() || rvas.back() != kUnassignedRVA);
181
182 size_t num_distinct_rva = 0;
183 for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance())
184 ++num_distinct_rva;
185
186 // Reserve space for |labels_|, populate with sorted RVA and repeats.
187 DCHECK(labels_.empty());
188 labels_.reserve(num_distinct_rva);
189 for (CRV it(rvas.begin(), rvas.end()); it.has_more(); it.advance()) {
190 labels_.push_back(Label(*it.cur()));
191 base::CheckedNumeric<uint32_t> count = it.repeat();
192 labels_.back().count_ = count.ValueOrDie();
193 }
208 } 194 }
209 195
210 } // namespace courgette 196 } // namespace courgette
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698