Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d20108d0 authored by Christopher Tate's avatar Christopher Tate Committed by Chirayu Desai
Browse files

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
parent 7e37473e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ LOCAL_SRC_FILES := \
	StringPool.cpp \
	XMLNode.cpp \
	ResourceFilter.cpp \
	ResourceIdCache.cpp \
	ResourceTable.cpp \
	Images.cpp \
	Resource.cpp \
+107 −0
Original line number Diff line number Diff line
//
// 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);
}

}
+30 −0
Original line number Diff line number Diff line
//
// Copyright 2012 The Android Open Source Project
//
// Manage a resource ID cache.

#ifndef RESOURCE_ID_CACHE_H
#define RESOURCE_ID_CACHE_H

namespace android {
class android::String16;

class ResourceIdCache {
public:
    static uint32_t lookup(const android::String16& package,
            const android::String16& type,
            const android::String16& name,
            bool onlyPublic);

    static uint32_t store(const android::String16& package,
            const android::String16& type,
            const android::String16& name,
            bool onlyPublic,
            uint32_t resId);

    static void dump(void);
};

}

#endif
+10 −5
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@

#include "XMLNode.h"
#include "ResourceFilter.h"
#include "ResourceIdCache.h"

#include <androidfw/ResourceTypes.h>
#include <utils/ByteOrder.h>
@@ -1999,6 +2000,9 @@ uint32_t ResourceTable::getResId(const String16& package,
                                 const String16& name,
                                 bool onlyPublic) const
{
    uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
    if (id != 0) return id;     // cache hit

    sp<Package> p = mPackages.valueFor(package);
    if (p == NULL) return 0;

@@ -2017,11 +2021,10 @@ uint32_t ResourceTable::getResId(const String16& package,
        }
        
        if (Res_INTERNALID(rid)) {
            return rid;
            return ResourceIdCache::store(package, type, name, onlyPublic, rid);
        }
        return Res_MAKEID(p->getAssignedId()-1,
                          Res_GETTYPE(rid),
                          Res_GETENTRY(rid));
        return ResourceIdCache::store(package, type, name, onlyPublic,
                Res_MAKEID(p->getAssignedId()-1, Res_GETTYPE(rid), Res_GETENTRY(rid)));
    }

    sp<Type> t = p->getTypes().valueFor(type);
@@ -2030,7 +2033,9 @@ uint32_t ResourceTable::getResId(const String16& package,
    if (c == NULL) return 0;
    int32_t ei = c->getEntryIndex();
    if (ei < 0) return 0;
    return getResId(p, t, ei);

    return ResourceIdCache::store(package, type, name, onlyPublic,
            getResId(p, t, ei));
}

uint32_t ResourceTable::getResId(const String16& ref,