summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yurii Zubrytskyi <zyy@google.com> 2024-06-13 17:51:17 -0700
committer Yurii Zubrytskyi <zyy@google.com> 2024-06-13 17:51:17 -0700
commit85e49ba0c47322c44ba2230c95bed97d60408a75 (patch)
tree058bef44ed55436272eec5802d6522319658baf1
parent8fb681e6c4874d08cc4053fc8749e4586441f4fe (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.cpp41
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];