summaryrefslogtreecommitdiffstats
path: root/runtime/base/allocator.h
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-08-25 13:08:22 -0700
committerMathieu Chartier <mathieuc@google.com>2014-08-29 18:57:35 -0700
commitbad0267eaab9d6a522d05469ff90501deefdb88b (patch)
tree1ce689b75184cb322b9edde34d7af938c658a6ae /runtime/base/allocator.h
parent0772a9d99c8774463c9076824340eaa4eb66f47f (diff)
downloadart-bad0267eaab9d6a522d05469ff90501deefdb88b.zip
art-bad0267eaab9d6a522d05469ff90501deefdb88b.tar.gz
art-bad0267eaab9d6a522d05469ff90501deefdb88b.tar.bz2
Add native memory accounting through custom allocator.
Added a custom allocator that lets you pass in a special tag which specifices where the allocation came from. This is used when dumping. The performance overhead is low since each allocation only does a atomic add/sub for each allocation/free. The measurements are dumped to traces.txt during SIGQUIT. Example output: I/art (27274): AllocatorTagHeap active=120 max=120 total=168 I/art (27274): AllocatorTagMonitorList active=1572 max=6240 total=11724 I/art (27274): AllocatorTagClassTable active=185208 max=185208 total=268608 I/art (27274): AllocatorTagInternTable active=430368 max=430368 total=436080 I/art (27274): AllocatorTagMaps active=5616 max=6168 total=34392 I/art (27274): AllocatorTagLOS active=1024 max=1536 total=2044 I/art (27274): AllocatorTagSafeMap active=0 max=51936 total=533688 I/art (27274): AllocatorTagLOSMaps active=144 max=1248 total=5760 I/art (27274): AllocatorTagReferenceTable active=10944 max=11840 total=19136 I/art (27274): AllocatorTagHeapBitmap active=32 max=40 total=56 I/art (27274): AllocatorTagHeapBitmapLOS active=8 max=8 total=8 I/art (27274): AllocatorTagVerifier active=0 max=18844 total=1073156 I/art (27274): AllocatorTagModUnionCardSet active=5300 max=5920 total=56020 I/art (27274): AllocatorTagModUnionReferenceArray active=24864 max=24864 total=24864 I/art (27274): AllocatorTagJNILibrarires active=320 max=320 total=320 I/art (27274): AllocatorTagOatFile active=1400 max=1400 total=5852 Change-Id: Ibb470ef2e9c9a24563bb46422d46a55799704d82 (cherry picked from commit 5369c40f75fdcb1be7a7c06db212ce965c83a164)
Diffstat (limited to 'runtime/base/allocator.h')
-rw-r--r--runtime/base/allocator.h113
1 files changed, 113 insertions, 0 deletions
diff --git a/runtime/base/allocator.h b/runtime/base/allocator.h
index 917bf0b..a7adb02 100644
--- a/runtime/base/allocator.h
+++ b/runtime/base/allocator.h
@@ -17,10 +17,17 @@
#ifndef ART_RUNTIME_BASE_ALLOCATOR_H_
#define ART_RUNTIME_BASE_ALLOCATOR_H_
+#include <map>
+
+#include "atomic.h"
#include "base/macros.h"
+#include "base/mutex.h"
+#include "utils.h"
namespace art {
+static constexpr bool kEnableTrackingAllocator = false;
+
class Allocator {
public:
static Allocator* GetMallocAllocator();
@@ -36,6 +43,112 @@ class Allocator {
DISALLOW_COPY_AND_ASSIGN(Allocator);
};
+// Used by TrackedAllocators.
+enum AllocatorTag {
+ kAllocatorTagHeap,
+ kAllocatorTagMonitorList,
+ kAllocatorTagClassTable,
+ kAllocatorTagInternTable,
+ kAllocatorTagMaps,
+ kAllocatorTagLOS,
+ kAllocatorTagSafeMap,
+ kAllocatorTagLOSMaps,
+ kAllocatorTagReferenceTable,
+ kAllocatorTagHeapBitmap,
+ kAllocatorTagHeapBitmapLOS,
+ kAllocatorTagMonitorPool,
+ kAllocatorTagLOSFreeList,
+ kAllocatorTagVerifier,
+ kAllocatorTagRememberedSet,
+ kAllocatorTagModUnionCardSet,
+ kAllocatorTagModUnionReferenceArray,
+ kAllocatorTagJNILibrarires,
+ kAllocatorTagCompileTimeClassPath,
+ kAllocatorTagOatFile,
+ kAllocatorTagDexFileVerifier,
+ kAllocatorTagCount, // Must always be last element.
+};
+std::ostream& operator<<(std::ostream& os, const AllocatorTag& tag);
+
+class TrackedAllocators {
+ public:
+ static bool Add(uint32_t tag, AtomicInteger* bytes_used);
+ static void Dump(std::ostream& os);
+ static void RegisterAllocation(AllocatorTag tag, uint64_t bytes) {
+ total_bytes_used_[tag].FetchAndAddSequentiallyConsistent(bytes);
+ uint64_t new_bytes = bytes_used_[tag].FetchAndAddSequentiallyConsistent(bytes) + bytes;
+ max_bytes_used_[tag].StoreRelaxed(std::max(max_bytes_used_[tag].LoadRelaxed(), new_bytes));
+ }
+ static void RegisterFree(AllocatorTag tag, uint64_t bytes) {
+ bytes_used_[tag].FetchAndSubSequentiallyConsistent(bytes);
+ }
+
+ private:
+ static Atomic<uint64_t> bytes_used_[kAllocatorTagCount];
+ static Atomic<uint64_t> max_bytes_used_[kAllocatorTagCount];
+ static Atomic<uint64_t> total_bytes_used_[kAllocatorTagCount];
+};
+
+// Tracking allocator, tracks how much memory is used.
+template<class T, AllocatorTag kTag>
+class TrackingAllocatorImpl {
+ public:
+ typedef typename std::allocator<T>::value_type value_type;
+ typedef typename std::allocator<T>::size_type size_type;
+ typedef typename std::allocator<T>::difference_type difference_type;
+ typedef typename std::allocator<T>::pointer pointer;
+ typedef typename std::allocator<T>::const_pointer const_pointer;
+ typedef typename std::allocator<T>::reference reference;
+ typedef typename std::allocator<T>::const_reference const_reference;
+
+ // Used internally by STL data structures.
+ template <class U>
+ TrackingAllocatorImpl(const TrackingAllocatorImpl<U, kTag>& alloc) throw() {
+ }
+
+ // Used internally by STL data structures.
+ TrackingAllocatorImpl() throw() {
+ COMPILE_ASSERT(kTag < kAllocatorTagCount, must_be_less_than_count);
+ }
+
+ // Enables an allocator for objects of one type to allocate storage for objects of another type.
+ // Used internally by STL data structures.
+ template <class U>
+ struct rebind {
+ typedef TrackingAllocatorImpl<U, kTag> other;
+ };
+
+ pointer allocate(size_type n, const_pointer hint = 0) {
+ const size_t size = n * sizeof(T);
+ TrackedAllocators::RegisterAllocation(GetTag(), size);
+ return reinterpret_cast<pointer>(malloc(size));
+ }
+
+ template <typename PT>
+ void deallocate(PT p, size_type n) {
+ const size_t size = n * sizeof(T);
+ TrackedAllocators::RegisterFree(GetTag(), size);
+ free(p);
+ }
+
+ static AllocatorTag GetTag() {
+ return kTag;
+ }
+};
+
+template<class T, AllocatorTag kTag>
+// C++ doesn't allow template typedefs. This is a workaround template typedef which is
+// TrackingAllocatorImpl<T> if kEnableTrackingAllocator is true, std::allocator<T> otherwise.
+class TrackingAllocator : public TypeStaticIf<kEnableTrackingAllocator,
+ TrackingAllocatorImpl<T, kTag>,
+ std::allocator<T>>::type {
+};
+
+template<class Key, class T, AllocatorTag kTag, class Compare = std::less<Key>>
+class AllocationTrackingMultiMap : public std::multimap<
+ Key, T, Compare, TrackingAllocator<std::pair<Key, T>, kTag>> {
+};
+
} // namespace art
#endif // ART_RUNTIME_BASE_ALLOCATOR_H_