diff options
-rw-r--r-- | compiler/dex/quick/quick_compiler.cc | 5 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 5 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 9 | ||||
-rw-r--r-- | compiler/jit/jit_compiler.cc | 6 | ||||
-rw-r--r-- | runtime/base/arena_allocator.cc | 28 | ||||
-rw-r--r-- | runtime/base/arena_allocator.h | 6 | ||||
-rw-r--r-- | runtime/runtime.cc | 2 | ||||
-rw-r--r-- | runtime/runtime.h | 10 |
8 files changed, 51 insertions, 20 deletions
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc index 13a6d9d815..02d74a0691 100644 --- a/compiler/dex/quick/quick_compiler.cc +++ b/compiler/dex/quick/quick_compiler.cc @@ -628,12 +628,13 @@ CompiledMethod* QuickCompiler::Compile(const DexFile::CodeItem* code_item, DCHECK(driver->GetCompilerOptions().IsCompilationEnabled()); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Runtime* const runtime = Runtime::Current(); + ClassLinker* const class_linker = runtime->GetClassLinker(); InstructionSet instruction_set = driver->GetInstructionSet(); if (instruction_set == kArm) { instruction_set = kThumb2; } - CompilationUnit cu(driver->GetArenaPool(), instruction_set, driver, class_linker); + CompilationUnit cu(runtime->GetArenaPool(), instruction_set, driver, class_linker); CHECK((cu.instruction_set == kThumb2) || (cu.instruction_set == kArm64) || diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index d1291fa719..78dd6cc29e 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2412,8 +2412,9 @@ bool CompilerDriver::SkipCompilation(const std::string& method_name) { std::string CompilerDriver::GetMemoryUsageString(bool extended) const { std::ostringstream oss; - const ArenaPool* arena_pool = GetArenaPool(); - gc::Heap* heap = Runtime::Current()->GetHeap(); + Runtime* const runtime = Runtime::Current(); + const ArenaPool* arena_pool = runtime->GetArenaPool(); + gc::Heap* const heap = runtime->GetHeap(); oss << "arena alloc=" << PrettySize(arena_pool->GetBytesAllocated()); oss << " java alloc=" << PrettySize(heap->GetBytesAllocated()); #ifdef HAVE_MALLOC_H diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index f94966733f..28a82457cc 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -362,12 +362,6 @@ class CompilerDriver { support_boot_image_fixup_ = support_boot_image_fixup; } - ArenaPool* GetArenaPool() { - return &arena_pool_; - } - const ArenaPool* GetArenaPool() const { - return &arena_pool_; - } SwapAllocator<void>& GetSwapSpaceAllocator() { return *swap_space_allocator_.get(); } @@ -606,9 +600,6 @@ class CompilerDriver { void* compiler_context_; - // Arena pool used by the compiler. - ArenaPool arena_pool_; - bool support_boot_image_fixup_; // DeDuplication data structures, these own the corresponding byte arrays. diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index 04efa21f4e..a63e14a980 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -103,7 +103,7 @@ JitCompiler::~JitCompiler() { } bool JitCompiler::CompileMethod(Thread* self, mirror::ArtMethod* method) { - uint64_t start_time = NanoTime(); + const uint64_t start_time = NanoTime(); StackHandleScope<2> hs(self); self->AssertNoPendingException(); Runtime* runtime = Runtime::Current(); @@ -130,6 +130,8 @@ bool JitCompiler::CompileMethod(Thread* self, mirror::ArtMethod* method) { } } CompiledMethod* compiled_method(compiler_driver_->CompileMethod(self, h_method.Get())); + // Trim maps to reduce memory usage, TODO: measure how much this increases compile time. + runtime->GetArenaPool()->TrimMaps(); if (compiled_method == nullptr) { return false; } @@ -137,7 +139,7 @@ bool JitCompiler::CompileMethod(Thread* self, mirror::ArtMethod* method) { // Don't add the method if we are supposed to be deoptimized. bool result = false; if (!runtime->GetInstrumentation()->AreAllMethodsDeoptimized()) { - const void* code = Runtime::Current()->GetClassLinker()->GetOatMethodQuickCodeFor( + const void* code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor( h_method.Get()); if (code != nullptr) { // Already have some compiled code, just use this instead of linking. diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc index e6380bfe5b..70d138d4b9 100644 --- a/runtime/base/arena_allocator.cc +++ b/runtime/base/arena_allocator.cc @@ -26,8 +26,9 @@ namespace art { -// Memmap is a bit slower than malloc according to my measurements. -static constexpr bool kUseMemMap = false; +// Memmap is a bit slower than malloc to allocate, but this is mitigated by the arena pool which +// only allocates few arenas and recycles them afterwards. +static constexpr bool kUseMemMap = true; static constexpr bool kUseMemSet = true && kUseMemMap; static constexpr size_t kValgrindRedZoneBytes = 8; constexpr size_t Arena::kDefaultSize; @@ -129,8 +130,8 @@ Arena::Arena(size_t size) next_(nullptr) { if (kUseMemMap) { std::string error_msg; - map_ = MemMap::MapAnonymous("dalvik-arena", nullptr, size, PROT_READ | PROT_WRITE, false, false, - &error_msg); + map_ = MemMap::MapAnonymous("dalvik-LinearAlloc", nullptr, size, PROT_READ | PROT_WRITE, false, + false, &error_msg); CHECK(map_ != nullptr) << error_msg; memory_ = map_->Begin(); size_ = map_->Size(); @@ -148,8 +149,15 @@ Arena::~Arena() { } } +void Arena::Release() { + if (kUseMemMap && bytes_allocated_ > 0) { + map_->MadviseDontNeedAndZero(); + bytes_allocated_ = 0; + } +} + void Arena::Reset() { - if (bytes_allocated_) { + if (bytes_allocated_ > 0) { if (kUseMemSet || !kUseMemMap) { memset(Begin(), 0, bytes_allocated_); } else { @@ -162,6 +170,9 @@ void Arena::Reset() { ArenaPool::ArenaPool() : lock_("Arena pool lock"), free_arenas_(nullptr) { + if (kUseMemMap) { + MemMap::Init(); + } } ArenaPool::~ArenaPool() { @@ -189,6 +200,13 @@ Arena* ArenaPool::AllocArena(size_t size) { return ret; } +void ArenaPool::TrimMaps() { + MutexLock lock(Thread::Current(), lock_); + for (auto* arena = free_arenas_; arena != nullptr; arena = arena->next_) { + arena->Release(); + } +} + size_t ArenaPool::GetBytesAllocated() const { size_t total = 0; MutexLock lock(Thread::Current(), lock_); diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h index 92373919d4..04ca3eabb8 100644 --- a/runtime/base/arena_allocator.h +++ b/runtime/base/arena_allocator.h @@ -118,7 +118,10 @@ class Arena { static constexpr size_t kDefaultSize = 128 * KB; explicit Arena(size_t size = kDefaultSize); ~Arena(); + // Reset is for pre-use and uses memset for performance. void Reset(); + // Release is used inbetween uses and uses madvise for memory usage. + void Release(); uint8_t* Begin() { return memory_; } @@ -160,6 +163,9 @@ class ArenaPool { Arena* AllocArena(size_t size) LOCKS_EXCLUDED(lock_); void FreeArenaChain(Arena* first) LOCKS_EXCLUDED(lock_); size_t GetBytesAllocated() const LOCKS_EXCLUDED(lock_); + // Trim the maps in arenas by madvising, used by JIT to reduce memory usage. This only works if + // kUseMemMap is true. + void TrimMaps() LOCKS_EXCLUDED(lock_); private: mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 70de0dbf01..ac1040dfa3 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -251,6 +251,7 @@ Runtime::~Runtime() { VLOG(jit) << "Deleting jit"; jit_.reset(nullptr); } + arena_pool_.reset(); // Shutdown the fault manager if it was initialized. fault_manager.Shutdown(); @@ -787,6 +788,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) max_spins_before_thin_lock_inflation_ = runtime_options.GetOrDefault(Opt::MaxSpinsBeforeThinLockInflation); + arena_pool_.reset(new ArenaPool); monitor_list_ = new MonitorList; monitor_pool_ = MonitorPool::Create(); thread_list_ = new ThreadList; diff --git a/runtime/runtime.h b/runtime/runtime.h index 5078b7f1d6..4cddb5c255 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -28,6 +28,7 @@ #include "arch/instruction_set.h" #include "base/allocator.h" +#include "base/arena_allocator.h" #include "base/macros.h" #include "compiler_callbacks.h" #include "gc_root.h" @@ -545,6 +546,13 @@ class Runtime { void CreateJit(); + ArenaPool* GetArenaPool() { + return arena_pool_.get(); + } + const ArenaPool* GetArenaPool() const { + return arena_pool_.get(); + } + private: static void InitPlatformSignalHandlers(); @@ -608,6 +616,8 @@ class Runtime { gc::Heap* heap_; + std::unique_ptr<ArenaPool> arena_pool_; + // The number of spins that are done before thread suspension is used to forcibly inflate. size_t max_spins_before_thin_lock_inflation_; MonitorList* monitor_list_; |