Skip to content

Commit 5f958e9

Browse files
Christopher TateAndroid Git Automerger
authored andcommitted
am 67b38c4: Cache resource ID lookups in aapt
* commit '67b38c44e8b04b97e357664804d593823b2a34ed': Cache resource ID lookups in aapt
2 parents 24d966a + 67b38c4 commit 5f958e9

File tree

4 files changed

+148
-5
lines changed

4 files changed

+148
-5
lines changed

tools/aapt/Android.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ LOCAL_SRC_FILES := \
2020
StringPool.cpp \
2121
XMLNode.cpp \
2222
ResourceFilter.cpp \
23+
ResourceIdCache.cpp \
2324
ResourceTable.cpp \
2425
Images.cpp \
2526
Resource.cpp \

tools/aapt/ResourceIdCache.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//
2+
// Copyright 2012 The Android Open Source Project
3+
//
4+
// Manage a resource ID cache.
5+
6+
#define LOG_TAG "ResourceIdCache"
7+
8+
#include <utils/String16.h>
9+
#include <utils/Log.h>
10+
#include "ResourceIdCache.h"
11+
#include <map>
12+
using namespace std;
13+
14+
15+
static size_t mHits = 0;
16+
static size_t mMisses = 0;
17+
static size_t mCollisions = 0;
18+
19+
static const size_t MAX_CACHE_ENTRIES = 2048;
20+
static const android::String16 TRUE16("1");
21+
static const android::String16 FALSE16("0");
22+
23+
struct CacheEntry {
24+
// concatenation of the relevant strings into a single instance
25+
android::String16 hashedName;
26+
uint32_t id;
27+
28+
CacheEntry() {}
29+
CacheEntry(const android::String16& name, uint32_t resId) : hashedName(name), id(resId) { }
30+
};
31+
32+
static map< uint32_t, CacheEntry > mIdMap;
33+
34+
35+
// djb2; reasonable choice for strings when collisions aren't particularly important
36+
static inline uint32_t hashround(uint32_t hash, int c) {
37+
return ((hash << 5) + hash) + c; /* hash * 33 + c */
38+
}
39+
40+
static uint32_t hash(const android::String16& hashableString) {
41+
uint32_t hash = 5381;
42+
const char16_t* str = hashableString.string();
43+
while (int c = *str++) hash = hashround(hash, c);
44+
return hash;
45+
}
46+
47+
namespace android {
48+
49+
static inline String16 makeHashableName(const android::String16& package,
50+
const android::String16& type,
51+
const android::String16& name,
52+
bool onlyPublic) {
53+
String16 hashable = String16(name);
54+
hashable += type;
55+
hashable += package;
56+
hashable += (onlyPublic ? TRUE16 : FALSE16);
57+
return hashable;
58+
}
59+
60+
uint32_t ResourceIdCache::lookup(const android::String16& package,
61+
const android::String16& type,
62+
const android::String16& name,
63+
bool onlyPublic) {
64+
const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
65+
const uint32_t hashcode = hash(hashedName);
66+
map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode);
67+
if (item == mIdMap.end()) {
68+
// cache miss
69+
mMisses++;
70+
return 0;
71+
}
72+
73+
// legit match?
74+
if (hashedName == (*item).second.hashedName) {
75+
mHits++;
76+
return (*item).second.id;
77+
}
78+
79+
// collision
80+
mCollisions++;
81+
mIdMap.erase(hashcode);
82+
return 0;
83+
}
84+
85+
// returns the resource ID being stored, for callsite convenience
86+
uint32_t ResourceIdCache::store(const android::String16& package,
87+
const android::String16& type,
88+
const android::String16& name,
89+
bool onlyPublic,
90+
uint32_t resId) {
91+
if (mIdMap.size() < MAX_CACHE_ENTRIES) {
92+
const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
93+
const uint32_t hashcode = hash(hashedName);
94+
mIdMap[hashcode] = CacheEntry(hashedName, resId);
95+
}
96+
return resId;
97+
}
98+
99+
void ResourceIdCache::dump() {
100+
printf("ResourceIdCache dump:\n");
101+
printf("Size: %ld\n", mIdMap.size());
102+
printf("Hits: %ld\n", mHits);
103+
printf("Misses: %ld\n", mMisses);
104+
printf("(Collisions: %ld)\n", mCollisions);
105+
}
106+
107+
}

tools/aapt/ResourceIdCache.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// Copyright 2012 The Android Open Source Project
3+
//
4+
// Manage a resource ID cache.
5+
6+
#ifndef RESOURCE_ID_CACHE_H
7+
#define RESOURCE_ID_CACHE_H
8+
9+
namespace android {
10+
class android::String16;
11+
12+
class ResourceIdCache {
13+
public:
14+
static uint32_t lookup(const android::String16& package,
15+
const android::String16& type,
16+
const android::String16& name,
17+
bool onlyPublic);
18+
19+
static uint32_t store(const android::String16& package,
20+
const android::String16& type,
21+
const android::String16& name,
22+
bool onlyPublic,
23+
uint32_t resId);
24+
25+
static void dump(void);
26+
};
27+
28+
}
29+
30+
#endif

tools/aapt/ResourceTable.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "XMLNode.h"
1010
#include "ResourceFilter.h"
11+
#include "ResourceIdCache.h"
1112

1213
#include <androidfw/ResourceTypes.h>
1314
#include <utils/ByteOrder.h>
@@ -1998,6 +1999,9 @@ uint32_t ResourceTable::getResId(const String16& package,
19981999
const String16& name,
19992000
bool onlyPublic) const
20002001
{
2002+
uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
2003+
if (id != 0) return id; // cache hit
2004+
20012005
sp<Package> p = mPackages.valueFor(package);
20022006
if (p == NULL) return 0;
20032007

@@ -2016,11 +2020,10 @@ uint32_t ResourceTable::getResId(const String16& package,
20162020
}
20172021

20182022
if (Res_INTERNALID(rid)) {
2019-
return rid;
2023+
return ResourceIdCache::store(package, type, name, onlyPublic, rid);
20202024
}
2021-
return Res_MAKEID(p->getAssignedId()-1,
2022-
Res_GETTYPE(rid),
2023-
Res_GETENTRY(rid));
2025+
return ResourceIdCache::store(package, type, name, onlyPublic,
2026+
Res_MAKEID(p->getAssignedId()-1, Res_GETTYPE(rid), Res_GETENTRY(rid)));
20242027
}
20252028

20262029
sp<Type> t = p->getTypes().valueFor(type);
@@ -2029,7 +2032,9 @@ uint32_t ResourceTable::getResId(const String16& package,
20292032
if (c == NULL) return 0;
20302033
int32_t ei = c->getEntryIndex();
20312034
if (ei < 0) return 0;
2032-
return getResId(p, t, ei);
2035+
2036+
return ResourceIdCache::store(package, type, name, onlyPublic,
2037+
getResId(p, t, ei));
20332038
}
20342039

20352040
uint32_t ResourceTable::getResId(const String16& ref,

0 commit comments

Comments
 (0)