File: call_stack_table.cc

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (108 lines) | stat: -rw-r--r-- 3,377 bytes parent folder | download | duplicates (2)
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
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/metrics/leak_detector/call_stack_table.h"

#include <algorithm>

#include "components/metrics/leak_detector/call_stack_manager.h"

namespace metrics {
namespace leak_detector {

namespace {

using ValueType = LeakDetectorValueType;

// During leak analysis, we only want to examine the top
// |kMaxCountOfSuspciousStacks| entries.
const int kMaxCountOfSuspciousStacks = 16;

const int kInitialHashTableSize = 1999;

}  // namespace

size_t CallStackTable::StoredHash::operator()(
    const CallStack* call_stack) const {
  // The call stack object should already have a hash computed when it was
  // created.
  //
  // This is NOT the actual hash computation function for a new call stack.
  return call_stack->hash;
}

CallStackTable::CallStackTable(int call_stack_suspicion_threshold)
    : num_allocs_(0),
      num_frees_(0),
      entry_map_(kInitialHashTableSize),
      leak_analyzer_(kMaxCountOfSuspciousStacks,
                     call_stack_suspicion_threshold) {}

CallStackTable::~CallStackTable() {}

void CallStackTable::Add(const CallStack* call_stack) {
  ++entry_map_[call_stack].count;
  ++num_allocs_;
}

void CallStackTable::Remove(const CallStack* call_stack) {
  auto iter = entry_map_.find(call_stack);
  if (iter == entry_map_.end())
    return;
  uint32_t& count_for_call_stack = iter->second.count;
  --count_for_call_stack;
  ++num_frees_;

  // Delete zero-alloc entries to free up space.
  if (count_for_call_stack == 0)
    entry_map_.erase(iter);
}

void CallStackTable::TestForLeaks() {
  // Add all entries to the ranked list.
  RankedSet ranked_entries(kMaxCountOfSuspciousStacks);
  GetTopCallStacks(&ranked_entries);
  leak_analyzer_.AddSample(std::move(ranked_entries));
}

void CallStackTable::GetTopCallStacks(RankedSet* top_entries) const {
  for (const auto& call_stack_count_info : entry_map_) {
    top_entries->AddCallStack(call_stack_count_info.first,
                              call_stack_count_info.second.count);
  }
}

void CallStackTable::UpdateLastDropInfo(size_t timestamp) {
  for (auto& call_stack_and_info : entry_map_) {
    auto& count_info = call_stack_and_info.second;

    // If the |previous_count| is 0 then we need to initialize info.
    if (count_info.previous_count == 0 ||
        count_info.count < count_info.previous_count) {
      count_info.last_drop_timestamp = timestamp;
      count_info.last_drop_count = count_info.count;
    }
    count_info.previous_count = count_info.count;
  }
}

void CallStackTable::GetLastUptrendInfo(
    const CallStack* call_stack, size_t timestamp, size_t* timestamp_delta,
    uint32_t* count_delta) const {
  const auto& call_stack_count_info_iter = entry_map_.find(call_stack);

  if (call_stack_count_info_iter != entry_map_.end()) {
    const auto& count_info = call_stack_count_info_iter->second;
    *timestamp_delta = timestamp - count_info.last_drop_timestamp;
    *count_delta = count_info.count - count_info.last_drop_count;
  } else {
    DLOG(WARNING) << "Accessing information about a call stack that has not "
                  << "been recorded";
    *timestamp_delta = timestamp;
    *count_delta = 0;
  }
}

}  // namespace leak_detector
}  // namespace metrics