Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
InsetsStateController: Replace ArrayMap with HashMap for performance
When opening and closing activities in Settings, a significant amount of CPU time is spent looking up ArrayMap entries, as reported by simpleperf: 0.12% /system/framework/arm64/boot-framework.oat android.util.ArrayMap.binarySearchHashes InsetsStateController is responsible for a significant portion of the time spent in ArrayMap lookups: 0.08% 0.08% /system/framework/arm64/boot-framework.oat android.util.ArrayMap.binarySearchHashes | -- android.util.ArrayMap.binarySearchHashes | --50.00%-- android.util.ArrayMap.indexOf | |--36.71%-- android.util.ArrayMap.get | |--0.87%-- [hit in function] | | | |--6.67%-- com.android.server.wm.InsetsStateController.peekSourceProvider | | | | | |--68.77%-- com.android.server.wm.DisplayPolicy.beginLayoutLw | | | com.android.server.wm.DisplayContent.performLayoutNoTrace | | | com.android.server.wm.DisplayContent.performLayout | | | com.android.server.wm.DisplayContent.applySurfaceChangesTransaction | | | com.android.server.wm.RootWindowContainer.applySurfaceChangesTransaction | | | com.android.server.wm.RootWindowContainer.performSurfacePlacementNoTrace | | | com.android.server.wm.RootWindowContainer.performSurfacePlacement | | | com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop | | | com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement | | | com.android.server.wm.WindowManagerService.relayoutWindow | | | com.android.server.wm.Session.relayout | | | android.view.IWindowSession$Stub.onTransact | | | com.android.server.wm.Session.onTransact | | | android.os.Binder.execTransactInternal | | | android.os.Binder.execTransact | | | art_quick_invoke_stub | | | art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) | | | art::JValue art::InvokeVirtualOrInterfaceWithVarArgs<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, std::__va_list) | | | art::JValue art::InvokeVirtualOrInterfaceWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list) | | | art::JNI<false>::CallBooleanMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list) | | | _JNIEnv::CallBooleanMethod(_jobject*, _jmethodID*, ...) | | | JavaBBinder::onTransact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int) | | | android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int) | | | android::IPCThreadState::executeCommand(int) | | | android::IPCThreadState::getAndExecuteCommand() | | | android::IPCThreadState::joinThreadPool(bool) | | | android::PoolThread::threadLoop() | | | android::Thread::_threadLoop(void*) | | | android::AndroidRuntime::javaThreadShell(void*) | | | thread_data_t::trampoline(thread_data_t const*) | | | __pthread_start(void*) | | | __start_thread | | | | | --31.23%-- com.android.server.wm.DisplayPolicy.updateHideNavInputEventReceiver | | com.android.server.wm.InsetsPolicy.updateBarControlTarget | | com.android.server.wm.DisplayPolicy.updateSystemUiVisibilityLw | | com.android.server.wm.DisplayPolicy.finishPostLayoutPolicyLw | | com.android.server.wm.DisplayContent.applySurfaceChangesTransaction | | com.android.server.wm.RootWindowContainer.applySurfaceChangesTransaction | | com.android.server.wm.RootWindowContainer.performSurfacePlacementNoTrace | | com.android.server.wm.RootWindowContainer.performSurfacePlacement | | com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop | | com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement | | com.android.server.wm.WindowManagerService.postWindowRemoveCleanupLocked | | com.android.server.wm.WindowState.removeImmediately | | com.android.server.wm.WindowState.removeIfPossible | | com.android.server.wm.WindowState.removeIfPossible | | com.android.server.wm.WindowManagerService.removeWindow | | com.android.server.wm.Session.remove | | android.view.IWindowSession$Stub.onTransact | | com.android.server.wm.Session.onTransact | | android.os.Binder.execTransactInternal | | android.os.Binder.execTransact | | art_quick_invoke_stub | | art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) | | art::JValue art::InvokeVirtualOrInterfaceWithVarArgs<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, std::__va_list) | | art::JValue art::InvokeVirtualOrInterfaceWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list) | | art::JNI<false>::CallBooleanMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list) | | _JNIEnv::CallBooleanMethod(_jobject*, _jmethodID*, ...) | | JavaBBinder::onTransact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int) | | android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int) | | android::IPCThreadState::executeCommand(int) | | android::IPCThreadState::getAndExecuteCommand() | | android::IPCThreadState::joinThreadPool(bool) | | android::PoolThread::threadLoop() | | android::Thread::_threadLoop(void*) | | android::AndroidRuntime::javaThreadShell(void*) | | thread_data_t::trampoline(thread_data_t const*) | | __pthread_start(void*) | | __start_thread | | Empirical testing reveals that mProviders usually contains 9 entries, at which HashMap is 34% faster than ArrayMap for lookups and 57% faster [1] for insertions. The increased memory usage should be negligible at this size, so we can safely convert the map to a HashMap in order to improve performance in this hotpath. [1] https://docs.google.com/spreadsheets/d/136UJS2yVlZyPx30KDNgj4AWldkp9xbzIcWkLFj9RGgk/edit Test: simpleperf record -a; verify that InsetsStateController no longer appears under ArrayMap.binarySearchHashes Change-Id: Ic08d4c3e56cf10b322eabc115de441c6c5f4a898
- Loading branch information