Modify TextLayoutCache to use new LRU cache
This patch modifies TextLayoutCache to use the new hash-based LRU
caching mechanism, which should be significantly faster than the
old GenerationCache implementation.
Change-Id: I6170462ad93a56156a731a2927680164d62b5cfc
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 4669c37..dce48a3 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "TextLayoutCache"
+#include <utils/JenkinsHash.h>
+
#include "TextLayoutCache.h"
#include "TextLayout.h"
#include "SkFontHost.h"
@@ -38,7 +40,7 @@
TextLayoutCache::TextLayoutCache(TextLayoutShaper* shaper) :
mShaper(shaper),
- mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> >::kUnlimitedCapacity),
+ mCache(LruCache<TextLayoutCacheKey, sp<TextLayoutValue> >::kUnlimitedCapacity),
mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)),
mCacheHitCount(0), mNanosecondsSaved(0) {
init();
@@ -199,11 +201,7 @@
float remainingPercent = 100 * ((mMaxSize - mSize) / ((float)mMaxSize));
float timeRunningInSec = (systemTime(SYSTEM_TIME_MONOTONIC) - mCacheStartTime) / 1000000000;
- size_t bytes = 0;
size_t cacheSize = mCache.size();
- for (size_t i = 0; i < cacheSize; i++) {
- bytes += mCache.getKeyAt(i).getSize() + mCache.getValueAt(i)->getSize();
- }
ALOGD("------------------------------------------------");
ALOGD("Cache stats");
@@ -212,7 +210,7 @@
ALOGD("running : %.0f seconds", timeRunningInSec);
ALOGD("entries : %d", cacheSize);
ALOGD("max size : %d bytes", mMaxSize);
- ALOGD("used : %d bytes according to mSize, %d bytes actual", mSize, bytes);
+ ALOGD("used : %d bytes according to mSize", mSize);
ALOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent);
ALOGD("hits : %d", mCacheHitCount);
ALOGD("saved : %0.6f ms", mNanosecondsSaved * 0.000001f);
@@ -302,6 +300,23 @@
return sizeof(TextLayoutCacheKey) + sizeof(UChar) * contextCount;
}
+hash_t TextLayoutCacheKey::hash() const {
+ uint32_t hash = JenkinsHashMix(0, start);
+ hash = JenkinsHashMix(hash, count);
+ /* contextCount not needed because it's included in text, below */
+ hash = JenkinsHashMix(hash, hash_type(typeface));
+ hash = JenkinsHashMix(hash, hash_type(textSize));
+ hash = JenkinsHashMix(hash, hash_type(textSkewX));
+ hash = JenkinsHashMix(hash, hash_type(textScaleX));
+ hash = JenkinsHashMix(hash, flags);
+ hash = JenkinsHashMix(hash, hinting);
+ hash = JenkinsHashMix(hash, variant);
+ // Note: leaving out language is not problematic, as equality comparisons
+ // are still valid - the only bad thing that could happen is collisions.
+ hash = JenkinsHashMixShorts(hash, getText(), contextCount);
+ return JenkinsHashWhiten(hash);
+}
+
/**
* TextLayoutCacheValue
*/
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 9994393..22de523 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -22,7 +22,7 @@
#include <stddef.h>
#include <utils/threads.h>
#include <utils/String16.h>
-#include <utils/GenerationCache.h>
+#include <utils/LruCache.h>
#include <utils/KeyedVector.h>
#include <utils/Compare.h>
#include <utils/RefBase.h>
@@ -85,6 +85,15 @@
inline const UChar* getText() const { return textCopy.string(); }
+ bool operator==(const TextLayoutCacheKey& other) const {
+ return compare(*this, other) == 0;
+ }
+
+ bool operator!=(const TextLayoutCacheKey& other) const {
+ return compare(*this, other) != 0;
+ }
+
+ hash_t hash() const;
private:
String16 textCopy;
size_t start;
@@ -110,6 +119,10 @@
return TextLayoutCacheKey::compare(lhs, rhs);
}
+inline hash_t hash_type(const TextLayoutCacheKey& key) {
+ return key.hash();
+}
+
/*
* TextLayoutValue is the Cache value
*/
@@ -276,7 +289,7 @@
Mutex mLock;
bool mInitialized;
- GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache;
+ LruCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache;
uint32_t mSize;
uint32_t mMaxSize;