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

Side by Side Diff: components/metrics/leak_detector/leak_detector_impl.cc

Issue 2417403002: Revert of Leak reports collect information about the last uptrend (Closed)
Patch Set: Created 4 years, 2 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 "leak_detector_impl.h" 5 #include "leak_detector_impl.h"
6 6
7 #include <inttypes.h> 7 #include <inttypes.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <algorithm> // For std::move 10 #include <algorithm> // For std::move
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 if (call_stack) { 166 if (call_stack) {
167 if (entry->stack_table) 167 if (entry->stack_table)
168 entry->stack_table->Remove(call_stack); 168 entry->stack_table->Remove(call_stack);
169 } 169 }
170 ++num_frees_; 170 ++num_frees_;
171 free_size_ += alloc_info.size; 171 free_size_ += alloc_info.size;
172 172
173 address_map_.erase(iter); 173 address_map_.erase(iter);
174 } 174 }
175 175
176 void LeakDetectorImpl::TestForLeaks(InternalVector<LeakReport>* reports, 176 void LeakDetectorImpl::TestForLeaks(InternalVector<LeakReport>* reports) {
177 size_t timestamp) {
178 // Add net alloc counts for each size to a ranked list. 177 // Add net alloc counts for each size to a ranked list.
179 RankedSet size_ranked_set(kRankedSetSize); 178 RankedSet size_ranked_set(kRankedSetSize);
180 for (size_t i = 0; i < size_entries_.size(); ++i) { 179 for (size_t i = 0; i < size_entries_.size(); ++i) {
181 const AllocSizeEntry& entry = size_entries_[i]; 180 const AllocSizeEntry& entry = size_entries_[i];
182 ValueType size_value(IndexToSize(i)); 181 ValueType size_value(IndexToSize(i));
183 size_ranked_set.Add(size_value, entry.GetNetAllocs()); 182 size_ranked_set.Add(size_value, entry.GetNetAllocs());
184 } 183 }
185 size_leak_analyzer_.AddSample(std::move(size_ranked_set)); 184 size_leak_analyzer_.AddSample(std::move(size_ranked_set));
186 185
187 RecordCurrentAllocationDataInHistory(timestamp); 186 RecordCurrentAllocationDataInHistory();
188 187
189 UpdateLeakCooldowns(); 188 UpdateLeakCooldowns();
190 189
191 // Get suspected leaks by size. 190 // Get suspected leaks by size.
192 for (const ValueType& size_value : size_leak_analyzer_.suspected_leaks()) { 191 for (const ValueType& size_value : size_leak_analyzer_.suspected_leaks()) {
193 uint32_t size = size_value.size(); 192 uint32_t size = size_value.size();
194 AllocSizeEntry* entry = &size_entries_[SizeToIndex(size)]; 193 AllocSizeEntry* entry = &size_entries_[SizeToIndex(size)];
195 if (entry->stack_table) 194 if (entry->stack_table)
196 continue; 195 continue;
197 entry->stack_table = new (CustomAllocator::Allocate(sizeof(CallStackTable))) 196 entry->stack_table = new (CustomAllocator::Allocate(sizeof(CallStackTable)))
(...skipping 26 matching lines...) Expand all
224 223
225 // Return reports by storing in |*reports|. 224 // Return reports by storing in |*reports|.
226 reports->resize(reports->size() + 1); 225 reports->resize(reports->size() + 1);
227 LeakReport* report = &reports->back(); 226 LeakReport* report = &reports->back();
228 report->alloc_size_bytes_ = size; 227 report->alloc_size_bytes_ = size;
229 report->call_stack_.resize(call_stack->depth); 228 report->call_stack_.resize(call_stack->depth);
230 for (size_t j = 0; j < call_stack->depth; ++j) { 229 for (size_t j = 0; j < call_stack->depth; ++j) {
231 report->call_stack_[j] = GetOffset(call_stack->stack[j]); 230 report->call_stack_[j] = GetOffset(call_stack->stack[j]);
232 } 231 }
233 232
234 StoreHistoricalDataInReport(size, call_stack, report, timestamp); 233 StoreHistoricalDataInReport(size, call_stack, report);
235 ResetLeakCooldown(size, call_stack); 234 ResetLeakCooldown(size, call_stack);
236 } 235 }
237 } 236 }
238 } 237 }
239 238
240 LeakDetectorImpl::AllocSizeEntry::AllocSizeEntry() : num_allocs(0), 239 LeakDetectorImpl::AllocSizeEntry::AllocSizeEntry() : num_allocs(0),
241 num_frees(0), 240 num_frees(0),
242 stack_table(nullptr) {} 241 stack_table(nullptr) {}
243 242
244 LeakDetectorImpl::AllocSizeEntry::~AllocSizeEntry() {} 243 LeakDetectorImpl::AllocSizeEntry::~AllocSizeEntry() {}
245 244
246 size_t LeakDetectorImpl::AddressHash::operator()(uintptr_t addr) const { 245 size_t LeakDetectorImpl::AddressHash::operator()(uintptr_t addr) const {
247 return base::Hash(reinterpret_cast<const char*>(&addr), sizeof(addr)); 246 return base::Hash(reinterpret_cast<const char*>(&addr), sizeof(addr));
248 } 247 }
249 248
250 uintptr_t LeakDetectorImpl::GetOffset(const void* ptr) const { 249 uintptr_t LeakDetectorImpl::GetOffset(const void* ptr) const {
251 uintptr_t ptr_value = reinterpret_cast<uintptr_t>(ptr); 250 uintptr_t ptr_value = reinterpret_cast<uintptr_t>(ptr);
252 if (ptr_value >= mapping_addr_ && ptr_value < mapping_addr_ + mapping_size_) 251 if (ptr_value >= mapping_addr_ && ptr_value < mapping_addr_ + mapping_size_)
253 return ptr_value - mapping_addr_; 252 return ptr_value - mapping_addr_;
254 return UINTPTR_MAX; 253 return UINTPTR_MAX;
255 } 254 }
256 255
257 void LeakDetectorImpl::RecordCurrentAllocationDataInHistory(size_t timestamp) { 256 void LeakDetectorImpl::RecordCurrentAllocationDataInHistory() {
258 // Record a snapshot of the current size table. 257 // Record a snapshot of the current size table.
259 InternalVector<uint32_t> current_size_table_record; 258 InternalVector<uint32_t> current_size_table_record;
260 current_size_table_record.reserve(kNumSizeEntriesInHistory); 259 current_size_table_record.reserve(kNumSizeEntriesInHistory);
261 for (const AllocSizeEntry& entry : size_entries_) { 260 for (const AllocSizeEntry& entry : size_entries_) {
262 if (current_size_table_record.size() == kNumSizeEntriesInHistory) 261 if (current_size_table_record.size() == kNumSizeEntriesInHistory)
263 break; 262 break;
264 current_size_table_record.push_back(entry.GetNetAllocs()); 263 current_size_table_record.push_back(entry.GetNetAllocs());
265 } 264 }
266 size_breakdown_history_.emplace_back(std::move(current_size_table_record)); 265 size_breakdown_history_.emplace_back(std::move(current_size_table_record));
267 if (size_breakdown_history_.size() > kMaxNumHistoryEntries) 266 if (size_breakdown_history_.size() > kMaxNumHistoryEntries)
268 size_breakdown_history_.pop_front(); 267 size_breakdown_history_.pop_front();
269 268
270 // For each allocation size that has started profiling by call site, record a 269 // For each allocation size that has started profiling by call site, record a
271 // snapshot of the top call sites by number of allocations. 270 // snapshot of the top call sites by number of allocations.
272 for (AllocSizeEntry& entry : size_entries_) { 271 for (AllocSizeEntry& entry : size_entries_) {
273 if (!entry.stack_table) 272 if (!entry.stack_table)
274 continue; 273 continue;
275 RankedSet top_call_stacks(kNumTopCallStacksInHistory); 274 RankedSet top_call_stacks(kNumTopCallStacksInHistory);
276 entry.stack_table->GetTopCallStacks(&top_call_stacks); 275 entry.stack_table->GetTopCallStacks(&top_call_stacks);
277 entry.stack_table->UpdateLastDropInfo(timestamp);
278 entry.call_site_breakdown_history.push_back(std::move(top_call_stacks)); 276 entry.call_site_breakdown_history.push_back(std::move(top_call_stacks));
279 if (entry.call_site_breakdown_history.size() > kMaxNumHistoryEntries) 277 if (entry.call_site_breakdown_history.size() > kMaxNumHistoryEntries)
280 entry.call_site_breakdown_history.pop_front(); 278 entry.call_site_breakdown_history.pop_front();
281 } 279 }
282 } 280 }
283 281
284 void LeakDetectorImpl::StoreHistoricalDataInReport(size_t size, 282 void LeakDetectorImpl::StoreHistoricalDataInReport(size_t size,
285 const CallStack* call_site, 283 const CallStack* call_site,
286 LeakReport* report, 284 LeakReport* report) {
287 size_t timestamp) {
288 using AllocationBreakdown = LeakReport::AllocationBreakdown; 285 using AllocationBreakdown = LeakReport::AllocationBreakdown;
289 // Copy historical allocation data into the report. 286 // Copy historical allocation data into the report.
290 InternalVector<AllocationBreakdown>* dest = &report->alloc_breakdown_history_; 287 InternalVector<AllocationBreakdown>* dest = &report->alloc_breakdown_history_;
291 dest->reserve(size_breakdown_history_.size()); 288 dest->reserve(size_breakdown_history_.size());
292 289
293 // Store each frame of the breakdown by size. 290 // Store each frame of the breakdown by size.
294 for (const InternalVector<uint32_t>& breakdown : size_breakdown_history_) { 291 for (const InternalVector<uint32_t>& breakdown : size_breakdown_history_) {
295 dest->push_back(AllocationBreakdown()); 292 dest->push_back(AllocationBreakdown());
296 dest->back().counts_by_size = breakdown; 293 dest->back().counts_by_size = breakdown;
297 } 294 }
(...skipping 15 matching lines...) Expand all
313 std::advance(dest_iter, dest->size() - src.size()); 310 std::advance(dest_iter, dest->size() - src.size());
314 311
315 while (src_iter != src.end() && dest_iter != dest->end()) { 312 while (src_iter != src.end() && dest_iter != dest->end()) {
316 const RankedSet& ranked_call_sites = *src_iter; 313 const RankedSet& ranked_call_sites = *src_iter;
317 auto find_call_site_iter = ranked_call_sites.FindCallStack(call_site); 314 auto find_call_site_iter = ranked_call_sites.FindCallStack(call_site);
318 if (find_call_site_iter != ranked_call_sites.end()) 315 if (find_call_site_iter != ranked_call_sites.end())
319 dest_iter->count_for_call_stack = find_call_site_iter->count; 316 dest_iter->count_for_call_stack = find_call_site_iter->count;
320 ++src_iter; 317 ++src_iter;
321 ++dest_iter; 318 ++dest_iter;
322 } 319 }
323
324 size_entries_[SizeToIndex(size)].stack_table->GetLastUptrendInfo(
325 call_site, timestamp, &report->num_rising_intervals_,
326 &report->num_allocs_increase_);
327 } 320 }
328 321
329 bool LeakDetectorImpl::ReadyToGenerateReport( 322 bool LeakDetectorImpl::ReadyToGenerateReport(
330 size_t size, 323 size_t size,
331 const CallStack* call_stack) const { 324 const CallStack* call_stack) const {
332 return cooldowns_per_leak_.find(std::make_pair(size, call_stack)) == 325 return cooldowns_per_leak_.find(std::make_pair(size, call_stack)) ==
333 cooldowns_per_leak_.end(); 326 cooldowns_per_leak_.end();
334 } 327 }
335 328
336 void LeakDetectorImpl::ResetLeakCooldown(size_t size, 329 void LeakDetectorImpl::ResetLeakCooldown(size_t size,
337 const CallStack* call_stack) { 330 const CallStack* call_stack) {
338 cooldowns_per_leak_[std::make_pair(size, call_stack)] = 331 cooldowns_per_leak_[std::make_pair(size, call_stack)] =
339 kNumSizeEntriesInHistory; 332 kNumSizeEntriesInHistory;
340 } 333 }
341 334
342 void LeakDetectorImpl::UpdateLeakCooldowns() { 335 void LeakDetectorImpl::UpdateLeakCooldowns() {
343 for (auto iter = cooldowns_per_leak_.begin(); 336 for (auto iter = cooldowns_per_leak_.begin();
344 iter != cooldowns_per_leak_.end(); 337 iter != cooldowns_per_leak_.end();
345 /* No iterating here */) { 338 /* No iterating here */) {
346 if (--iter->second > 0) { 339 if (--iter->second > 0) {
347 ++iter; 340 ++iter;
348 } else { 341 } else {
349 cooldowns_per_leak_.erase(iter++); 342 cooldowns_per_leak_.erase(iter++);
350 } 343 }
351 } 344 }
352 } 345 }
353 346
354 } // namespace leak_detector 347 } // namespace leak_detector
355 } // namespace metrics 348 } // namespace metrics
OLDNEW
« no previous file with comments | « components/metrics/leak_detector/leak_detector_impl.h ('k') | components/metrics/leak_detector/leak_detector_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698