summaryrefslogtreecommitdiffstats
path: root/tools/aapt/ResourceIdCache.cpp
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2012-11-16 15:58:08 -0800
committerChristopher Tate <ctate@google.com>2012-11-27 18:28:49 -0800
commitd8dde13a63565dcd72bcf03a5088407b737ba793 (patch)
tree671cd9a2e230b1f960e673e8c2c1bbd3b535d9cc /tools/aapt/ResourceIdCache.cpp
parentaeb6268645d571dfc9f2d387a7ad2471039ddb54 (diff)
downloadframeworks_base-d8dde13a63565dcd72bcf03a5088407b737ba793.zip
frameworks_base-d8dde13a63565dcd72bcf03a5088407b737ba793.tar.gz
frameworks_base-d8dde13a63565dcd72bcf03a5088407b737ba793.tar.bz2
Cache resource ID lookups in aapt
This speeds up certain workloads considerably, particularly those involved in buildling apps via the SDK. Windows-based use should particularly benefit from the change. Change-Id: I29f4b3a77400b201ee219729cc28a5e359c0c5e8
Diffstat (limited to 'tools/aapt/ResourceIdCache.cpp')
-rw-r--r--tools/aapt/ResourceIdCache.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/tools/aapt/ResourceIdCache.cpp b/tools/aapt/ResourceIdCache.cpp
new file mode 100644
index 0000000..e03f4f6
--- /dev/null
+++ b/tools/aapt/ResourceIdCache.cpp
@@ -0,0 +1,107 @@
+//
+// Copyright 2012 The Android Open Source Project
+//
+// Manage a resource ID cache.
+
+#define LOG_TAG "ResourceIdCache"
+
+#include <utils/String16.h>
+#include <utils/Log.h>
+#include "ResourceIdCache.h"
+#include <map>
+using namespace std;
+
+
+static size_t mHits = 0;
+static size_t mMisses = 0;
+static size_t mCollisions = 0;
+
+static const size_t MAX_CACHE_ENTRIES = 2048;
+static const android::String16 TRUE16("1");
+static const android::String16 FALSE16("0");
+
+struct CacheEntry {
+ // concatenation of the relevant strings into a single instance
+ android::String16 hashedName;
+ uint32_t id;
+
+ CacheEntry() {}
+ CacheEntry(const android::String16& name, uint32_t resId) : hashedName(name), id(resId) { }
+};
+
+static map< uint32_t, CacheEntry > mIdMap;
+
+
+// djb2; reasonable choice for strings when collisions aren't particularly important
+static inline uint32_t hashround(uint32_t hash, int c) {
+ return ((hash << 5) + hash) + c; /* hash * 33 + c */
+}
+
+static uint32_t hash(const android::String16& hashableString) {
+ uint32_t hash = 5381;
+ const char16_t* str = hashableString.string();
+ while (int c = *str++) hash = hashround(hash, c);
+ return hash;
+}
+
+namespace android {
+
+static inline String16 makeHashableName(const android::String16& package,
+ const android::String16& type,
+ const android::String16& name,
+ bool onlyPublic) {
+ String16 hashable = String16(name);
+ hashable += type;
+ hashable += package;
+ hashable += (onlyPublic ? TRUE16 : FALSE16);
+ return hashable;
+}
+
+uint32_t ResourceIdCache::lookup(const android::String16& package,
+ const android::String16& type,
+ const android::String16& name,
+ bool onlyPublic) {
+ const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
+ const uint32_t hashcode = hash(hashedName);
+ map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode);
+ if (item == mIdMap.end()) {
+ // cache miss
+ mMisses++;
+ return 0;
+ }
+
+ // legit match?
+ if (hashedName == (*item).second.hashedName) {
+ mHits++;
+ return (*item).second.id;
+ }
+
+ // collision
+ mCollisions++;
+ mIdMap.erase(hashcode);
+ return 0;
+}
+
+// returns the resource ID being stored, for callsite convenience
+uint32_t ResourceIdCache::store(const android::String16& package,
+ const android::String16& type,
+ const android::String16& name,
+ bool onlyPublic,
+ uint32_t resId) {
+ if (mIdMap.size() < MAX_CACHE_ENTRIES) {
+ const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
+ const uint32_t hashcode = hash(hashedName);
+ mIdMap[hashcode] = CacheEntry(hashedName, resId);
+ }
+ return resId;
+}
+
+void ResourceIdCache::dump() {
+ printf("ResourceIdCache dump:\n");
+ printf("Size: %ld\n", mIdMap.size());
+ printf("Hits: %ld\n", mHits);
+ printf("Misses: %ld\n", mMisses);
+ printf("(Collisions: %ld)\n", mCollisions);
+}
+
+}