diff options
| author | 2024-06-13 17:51:17 -0700 | |
|---|---|---|
| committer | 2024-06-13 17:51:17 -0700 | |
| commit | 85e49ba0c47322c44ba2230c95bed97d60408a75 (patch) | |
| tree | 058bef44ed55436272eec5802d6522319658baf1 | |
| parent | 8fb681e6c4874d08cc4053fc8749e4586441f4fe (diff) | |
[res] Optimize locale comparison and alias search
1. Locale comparison doesn't need to happen if the locales
aren't set at all, and an early check skips the function
call overhead
2. Staging resource aliases only exist for Framework resources,
and are constrained to a pretty short range. Given that
the binary search in STL doesn't check for the value to be
inside the array, most of the alias searches end up hitting
the worst case with the full log2(n) of halvings before they
fail to find it. An early check speeds up the resource
lookups by a whopping 10-15%.
Bug: 345562237
Test: build, boot, atest + performance tests
Change-Id: Ifd2c12c74df4b21a81609102291e6aabe38c2670
| -rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index a3dd9833219e..de9991a8be5e 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -2650,8 +2650,9 @@ bool ResTable_config::isBetterThan(const ResTable_config& o, return (mnc); } } - - if (isLocaleBetterThan(o, requested)) { + // Cheaper to check for the empty locales here before calling the function + // as we often can skip it completely. + if (requested->locale && (locale || o.locale) && isLocaleBetterThan(o, requested)) { return true; } @@ -7237,27 +7238,11 @@ void DynamicRefTable::addMapping(uint8_t buildPackageId, uint8_t runtimePackageI status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { uint32_t res = *resId; - size_t packageId = Res_GETPACKAGE(res) + 1; - if (!Res_VALIDID(res)) { // Cannot look up a null or invalid id, so no lookup needs to be done. return NO_ERROR; } - - const auto alias_it = std::lower_bound(mAliasId.begin(), mAliasId.end(), res, - [](const AliasMap::value_type& pair, uint32_t val) { return pair.first < val; }); - if (alias_it != mAliasId.end() && alias_it->first == res) { - // Rewrite the resource id to its alias resource id. Since the alias resource id is a - // compile-time id, it still needs to be resolved further. - res = alias_it->second; - } - - if (packageId == SYS_PACKAGE_ID || (packageId == APP_PACKAGE_ID && !mAppAsLib)) { - // No lookup needs to be done, app and framework package IDs are absolute. - *resId = res; - return NO_ERROR; - } - + const size_t packageId = Res_GETPACKAGE(res) + 1; if (packageId == 0 || (packageId == APP_PACKAGE_ID && mAppAsLib)) { // The package ID is 0x00. That means that a shared library is accessing // its own local resource. @@ -7267,6 +7252,24 @@ status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { *resId = (0xFFFFFF & (*resId)) | (((uint32_t) mAssignedPackageId) << 24); return NO_ERROR; } + // All aliases are coming from the framework, and usually have their own separate ID range, + // skipping the whole binary search is much more efficient than not finding anything. + if (packageId == SYS_PACKAGE_ID && !mAliasId.empty() && + res >= mAliasId.front().first && res <= mAliasId.back().first) { + const auto alias_it = std::lower_bound(mAliasId.begin(), mAliasId.end(), res, + [](const AliasMap::value_type& pair, + uint32_t val) { return pair.first < val; }); + if (alias_it != mAliasId.end() && alias_it->first == res) { + // Rewrite the resource id to its alias resource id. Since the alias resource id is a + // compile-time id, it still needs to be resolved further. + res = alias_it->second; + } + } + if (packageId == SYS_PACKAGE_ID || (packageId == APP_PACKAGE_ID && !mAppAsLib)) { + // No lookup needs to be done, app and framework package IDs are absolute. + *resId = res; + return NO_ERROR; + } // Do a proper lookup. uint8_t translatedId = mLookupTable[packageId]; |