diff options
author | 2021-12-01 17:09:08 +0000 | |
---|---|---|
committer | 2022-01-15 22:04:52 +0000 | |
commit | fa40e6e318b21d4a1885a6ffea6efc3c0b5cc1cd (patch) | |
tree | ea74f6947c5c6caaaf7a6fb3ece3369aec3a62c3 /runtime/interpreter/interpreter_cache-inl.h | |
parent | c5f41cd1a39472dbe2480c09a1ce20aeced2a9f6 (diff) |
Add thread-shared interpreter cache
The thread-local interpreter cache handles around 75% of method/field
lookups from the interpreter.
Add thread-shared interpreter cache which can be much bigger (since
we pay the memory just once rather then per thread). This increases
the cache hit rate to 90%.
This effectively halves the amount of time we spend in
'NterpGetMethod' (including DexCache lookups), which is the single
most expensive method during startup.
Furthermore, it also reduces the amount of time we spend resolving
methods by around 25% since DexCache entries get evicted less often.
The shared cache increases memory use by 256k per process, so also
reduce the fixed-size DexCache fields array, which balances it back.
Test: test.py --host
Change-Id: I3cd369613d47de117ab69d5bee00d4cf89b87913
Diffstat (limited to 'runtime/interpreter/interpreter_cache-inl.h')
-rw-r--r-- | runtime/interpreter/interpreter_cache-inl.h | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/runtime/interpreter/interpreter_cache-inl.h b/runtime/interpreter/interpreter_cache-inl.h new file mode 100644 index 0000000000..249df23b27 --- /dev/null +++ b/runtime/interpreter/interpreter_cache-inl.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_CACHE_INL_H_ +#define ART_RUNTIME_INTERPRETER_INTERPRETER_CACHE_INL_H_ + +#include "interpreter_cache.h" +#include "thread.h" + +namespace art { + +template<bool kSkipThreadLocal> +inline bool InterpreterCache::Get(Thread* self, const void* dex_instr, /* out */ size_t* value) { + DCHECK(self->GetInterpreterCache() == this) << "Must be called from owning thread"; + size_t key = reinterpret_cast<size_t>(dex_instr); + Entry& local_entry = thread_local_array_[IndexOf<kThreadLocalSize>(key)]; + if (kSkipThreadLocal) { + DCHECK_NE(local_entry.first, key) << "Expected cache miss"; + } else { + if (LIKELY(local_entry.first == key)) { + *value = local_entry.second; + return true; + } + } + Entry shared_entry = AtomicPairLoadAcquire(&shared_array_[IndexOf<kSharedSize>(key)]); + if (LIKELY(shared_entry.first == key)) { + // For simplicity, only update the cache if weak ref accesses are enabled. If + // they are disabled, this means the GC is processing the cache, and is + // reading it concurrently. + if (self->GetWeakRefAccessEnabled()) { + local_entry = shared_entry; // Copy to local array to make future lookup faster. + } + *value = shared_entry.second; + return true; + } + return false; +} + +inline void InterpreterCache::Set(Thread* self, const void* dex_instr, size_t value) { + DCHECK(self->GetInterpreterCache() == this) << "Must be called from owning thread"; + + // For simplicity, only update the cache if weak ref accesses are enabled. If + // they are disabled, this means the GC is processing the cache, and is + // reading it concurrently. + if (self->GetWeakRefAccessEnabled()) { + size_t key = reinterpret_cast<size_t>(dex_instr); + thread_local_array_[IndexOf<kThreadLocalSize>(key)] = {key, value}; + AtomicPairStoreRelease(&shared_array_[IndexOf<kSharedSize>(key)], {key, value}); + } +} + +} // namespace art + +#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_CACHE_INL_H_ |