Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fullallocationtracker.cc
Go to the documentation of this file.
1 
19 
20 #include <algorithm>
21 #include <map>
22 #include <vector>
23 
24 #include "ion/base/allocatable.h"
26 #include "ion/base/invalid.h"
27 #include "ion/base/lockguards.h"
28 #include "ion/base/logging.h"
31 #include "ion/port/mutex.h"
32 
33 namespace ion {
34 namespace base {
35 
37 
42 
43 
44 class FullAllocationTracker::Helper : public Allocatable {
45  public:
46  Helper()
47  : allocations_(*this),
48  active_map_(*this),
49  deallocation_count_(0U),
50  allocated_bytes_count_(0U),
51  deallocated_bytes_count_(0U),
52  active_memory_bytes_count_(0U) {}
53 
54  ~Helper() override;
55 
58  size_t AddAllocation(const void* memory, size_t size) {
59  LockGuard lock(&mutex_);
60  const size_t index = allocations_.size();
61  allocations_.push_back(Allocation(memory, size));
62  DCHECK(active_map_.find(memory) == active_map_.end());
63  active_map_[memory] = index;
64  allocated_bytes_count_ += size;
65  active_memory_bytes_count_ += size;
66  return index;
67  }
68 
71  size_t RemoveAllocation(const void* memory) {
72  LockGuard lock(&mutex_);
73  ActiveMap::iterator it = active_map_.find(memory);
74  if (it == active_map_.end()) {
75  return kInvalidIndex;
76  } else {
77  const size_t index = it->second;
78  DCHECK_LT(index, allocations_.size());
79  ++deallocation_count_;
80  const size_t size = allocations_[index].size;
81  deallocated_bytes_count_ += size;
82  DCHECK_LE(size, active_memory_bytes_count_);
83  active_memory_bytes_count_ -= size;
84  active_map_.erase(it);
85  return index;
86  }
87  }
88 
90  size_t GetAllocationCount() const {
91  LockGuard lock(&mutex_);
92  return allocations_.size();
93  }
94 
96  size_t GetDeallocationCount() const {
97  LockGuard lock(&mutex_);
98  return deallocation_count_;
99  }
100 
102  size_t GetAllocatedBytesCount() const {
103  LockGuard lock(&mutex_);
104  return allocated_bytes_count_;
105  }
106 
107  size_t GetDeallocatedBytesCount() const {
108  LockGuard lock(&mutex_);
109  return deallocated_bytes_count_;
110  }
111 
113  size_t GetActiveAllocationCount() const {
114  LockGuard lock(&mutex_);
115  return active_map_.size();
116  }
117 
119  size_t GetActiveAllocationBytesCount() const {
120  LockGuard lock(&mutex_);
121  return active_memory_bytes_count_;
122  }
123 
125  size_t GetAllocationBytesCount(size_t index) const {
126  LockGuard lock(&mutex_);
127  DCHECK_LT(index, allocations_.size());
128  return allocations_[index].size;
129  }
130 
131  private:
133  struct Allocation {
134  Allocation(const void* memory_in, size_t size_in)
135  : memory(memory_in), size(size_in) {}
136  const void* memory; // Pointer to allocated memory chunk.
137  size_t size; // Number of bytes allocated.
138  };
139 
141  const AllocVector<Allocation> GetActiveAllocations() const {
142  LockGuard lock(&mutex_);
146  AllocVector<Allocation> vec(*this);
147  vec.reserve(active_map_.size());
148  for (ActiveMap::const_iterator it = active_map_.begin();
149  it != active_map_.end(); ++it) {
150  DCHECK_LT(it->second, allocations_.size());
151  vec.push_back(allocations_[it->second]);
152  }
154  std::sort(vec.begin(), vec.end(), CompareAllocations);
155  return vec;
156  }
157 
160  static bool CompareAllocations(const Allocation& a0, const Allocation& a1) {
161  return a0.memory < a1.memory;
162  }
163 
165  AllocVector<Allocation> allocations_;
166 
169  typedef AllocMap<const void*, size_t> ActiveMap;
170  ActiveMap active_map_;
171 
173  size_t deallocation_count_;
174 
176  size_t allocated_bytes_count_;
177  size_t deallocated_bytes_count_;
178 
180  size_t active_memory_bytes_count_;
181 
183  mutable port::Mutex mutex_;
184 };
185 
186 FullAllocationTracker::Helper::~Helper() {
188  const AllocVector<Allocation> allocations = GetActiveAllocations();
189  if (!allocations.empty()) {
190  LOG(ERROR) << "FullAllocationTracker " << this << " destroyed with "
191  << allocations.size() << " active allocations:";
192  for (size_t i = 0; i < allocations.size(); ++i) {
193  const Allocation& a = allocations[i];
194  LOG(ERROR) << " [" << i << "] " << a.size << " bytes at " << a.memory;
195  }
196  }
197 }
198 
200 
205 
206 
208  : helper_(new(AllocationManager::GetMallocAllocator()) Helper),
209  tracing_ostream_(NULL) {}
210 
213  helper_.reset(NULL);
214 }
215 
217  const Allocator& allocator, size_t requested_size, const void* memory) {
218  const size_t index = helper_->AddAllocation(memory, requested_size);
219  if (tracing_ostream_) {
220  (*tracing_ostream_) << "FullAllocationTracker " << this << " [" << index
221  << "] Allocated " << requested_size << " bytes @ "
222  << memory << " with allocator " << &allocator << "\n";
223  }
224 }
225 
227  const Allocator& allocator, const void* memory) {
228  const size_t index = helper_->RemoveAllocation(memory);
229  if (index == kInvalidIndex) {
230  LOG(ERROR) << "FullAllocationTracker " << this << ": pointer " << memory
231  << " does not correspond to an active allocation";
232  } else {
233  if (tracing_ostream_) {
234  const size_t size = helper_->GetAllocationBytesCount(index);
235  (*tracing_ostream_) << "FullAllocationTracker " << this << " [" << index
236  << "] Deallocated " << size << " bytes @ " << memory
237  << " with allocator " << &allocator << "\n";
238  }
239  }
240 }
241 
243  return helper_->GetAllocationCount();
244 }
245 
247  return helper_->GetDeallocationCount();
248 }
249 
251  return helper_->GetAllocatedBytesCount();
252 }
253 
255  return helper_->GetDeallocatedBytesCount();
256 }
257 
259  return helper_->GetActiveAllocationCount();
260 }
261 
263  return helper_->GetActiveAllocationBytesCount();
264 }
265 
267  const AllocationSizeTrackerPtr& gpu_tracker) {}
269  return AllocationSizeTrackerPtr();
270 }
271 
272 } // namespace base
273 } // namespace ion
void SetGpuTracker(const AllocationSizeTrackerPtr &gpu_tracker) override
Sets/returns an AllocationSizeTracker instance used to track GPU memory allocations.
SharedPtr< AllocationSizeTracker > AllocationSizeTrackerPtr
Convenience typedef for shared pointer to a AllocationSizeTracker.
size_t GetAllocatedBytesCount() override
Returns the total number of memory ever allocated or deallocated, in bytes.
const size_t kInvalidIndex
kInvalidIndex is a size_t value that is very unlikely to be a valid index.
Definition: invalid.cc:23
size_t GetActiveAllocationCount() override
Returns the number of active allocations or the amount of memory in bytes used by active allocations...
#define DCHECK(expr)
Definition: logging.h:331
GenericLockGuard< port::Mutex > LockGuard
Convenient typedefs for ion::port::Mutex.
Definition: lockguards.h:192
AllocationManager is a singleton class that is used to manage Allocators used to allocate Ion objects...
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
AllocationSizeTrackerPtr GetGpuTracker() override
Allocator is an abstract base class for a memory allocator used for Ion objects derived from Allocata...
Definition: allocator.h:61
void TrackAllocation(const Allocator &allocator, size_t requested_size, const void *memory) override
AllocationTracker interface implementations.
Copyright 2016 Google Inc.
FullAllocationTracker()
FullAllocationTracker functions.
void TrackDeallocation(const Allocator &allocator, const void *memory) override
TrackDeallocation() is called immediately before an Allocator deallocates memory. ...
size_t GetAllocationCount() override
Returns the total number of tracked allocations or deallocations.
#define DCHECK_LE(val1, val2)
Definition: logging.h:334
port::Mutex mutex_
Protects shared access to the Allocator and FT_Library.
~FullAllocationTracker() override
The destructor is protected because all instances should be managed through SharedPtr.
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60
#define DCHECK_LT(val1, val2)
Definition: logging.h:335