diff options
author | 2018-11-01 14:21:33 -0700 | |
---|---|---|
committer | 2018-11-02 10:02:18 -0700 | |
commit | 8fc755804bc3eb7b55e4de0ac3b335efd5ca0309 (patch) | |
tree | 440b4c164ba6a506ed44e8ae31f5bb028dec2c88 /runtime/class_linker.cc | |
parent | 81ac31ded4df5d597aa603c53122fa1d74413b78 (diff) |
Smarter set intersection between app image and non boot image strings
If there are fewer non boot image strings in the runtime, iterate
over those strings instead of the set being newly added.
On AOSP, nonBootImageInternStrings is around 500.
Test: test-art-host
Bug: 116059983
Change-Id: I76b49f2090971cf593ba487889b35dfc1fa8cf13
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index e3dfdb3256..6a5e8b6d65 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1495,18 +1495,44 @@ void AppImageLoadingHelper::HandleAppImageStrings(gc::space::ImageSpace* space) intern_table->AddImageStringsToTable(space, [&](InternTable::UnorderedSet& interns) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_) { + const size_t non_boot_image_strings = intern_table->CountInterns( + /*visit_boot_images=*/false, + /*visit_non_boot_images=*/true); VLOG(image) << "AppImage:stringsInInternTableSize = " << interns.size(); - for (auto it = interns.begin(); it != interns.end(); ) { - ObjPtr<mirror::String> string = it->Read(); - ObjPtr<mirror::String> existing = intern_table->LookupWeakLocked(string); - if (existing == nullptr) { - existing = intern_table->LookupStrongLocked(string); - } - if (existing != nullptr) { - intern_remap.Put(string.Ptr(), existing.Ptr()); - it = interns.erase(it); - } else { - ++it; + VLOG(image) << "AppImage:nonBootImageInternStrings = " << non_boot_image_strings; + // Visit the smaller of the two sets to compute the intersection. + if (interns.size() < non_boot_image_strings) { + for (auto it = interns.begin(); it != interns.end(); ) { + ObjPtr<mirror::String> string = it->Read(); + ObjPtr<mirror::String> existing = intern_table->LookupWeakLocked(string); + if (existing == nullptr) { + existing = intern_table->LookupStrongLocked(string); + } + if (existing != nullptr) { + intern_remap.Put(string.Ptr(), existing.Ptr()); + it = interns.erase(it); + } else { + ++it; + } + } + } else { + intern_table->VisitInterns([&](const GcRoot<mirror::String>& root) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(Locks::intern_table_lock_) { + auto it = interns.find(root); + if (it != interns.end()) { + ObjPtr<mirror::String> existing = root.Read(); + intern_remap.Put(it->Read(), existing.Ptr()); + it = interns.erase(it); + } + }, /*visit_boot_images=*/false, /*visit_non_boot_images=*/true); + } + // Sanity check to ensure correctness. + if (kIsDebugBuild) { + for (GcRoot<mirror::String>& root : interns) { + ObjPtr<mirror::String> string = root.Read(); + CHECK(intern_table->LookupWeakLocked(string) == nullptr) << string->ToModifiedUtf8(); + CHECK(intern_table->LookupStrongLocked(string) == nullptr) << string->ToModifiedUtf8(); } } }); |