am b118a9d7: Merge "Change cache capacity depending on the dictionary size."
* commit 'b118a9d729b8ea58063a39396f60c7c5aa1c544b': Change cache capacity depending on the dictionary size.main
commit
0d86a015be
|
@ -43,6 +43,7 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
|
|
||||||
private long mNativeDict;
|
private long mNativeDict;
|
||||||
private final Locale mLocale;
|
private final Locale mLocale;
|
||||||
|
private final long mDictSize;
|
||||||
private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
|
private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
|
||||||
private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
|
private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
|
||||||
private final int[] mSpaceIndices = new int[MAX_RESULTS];
|
private final int[] mSpaceIndices = new int[MAX_RESULTS];
|
||||||
|
@ -62,7 +63,7 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
if (traverseSession == null) {
|
if (traverseSession == null) {
|
||||||
traverseSession = mDicTraverseSessions.get(traverseSessionId);
|
traverseSession = mDicTraverseSessions.get(traverseSessionId);
|
||||||
if (traverseSession == null) {
|
if (traverseSession == null) {
|
||||||
traverseSession = new DicTraverseSession(mLocale, mNativeDict);
|
traverseSession = new DicTraverseSession(mLocale, mNativeDict, mDictSize);
|
||||||
mDicTraverseSessions.put(traverseSessionId, traverseSession);
|
mDicTraverseSessions.put(traverseSessionId, traverseSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,6 +86,7 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
final boolean isUpdatable) {
|
final boolean isUpdatable) {
|
||||||
super(dictType);
|
super(dictType);
|
||||||
mLocale = locale;
|
mLocale = locale;
|
||||||
|
mDictSize = length;
|
||||||
mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
|
mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
|
||||||
loadDictionary(filename, offset, length, isUpdatable);
|
loadDictionary(filename, offset, length, isUpdatable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,16 +25,16 @@ public final class DicTraverseSession {
|
||||||
JniUtils.loadNativeLibrary();
|
JniUtils.loadNativeLibrary();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native long setDicTraverseSessionNative(String locale);
|
private static native long setDicTraverseSessionNative(String locale, long dictSize);
|
||||||
private static native void initDicTraverseSessionNative(long nativeDicTraverseSession,
|
private static native void initDicTraverseSessionNative(long nativeDicTraverseSession,
|
||||||
long dictionary, int[] previousWord, int previousWordLength);
|
long dictionary, int[] previousWord, int previousWordLength);
|
||||||
private static native void releaseDicTraverseSessionNative(long nativeDicTraverseSession);
|
private static native void releaseDicTraverseSessionNative(long nativeDicTraverseSession);
|
||||||
|
|
||||||
private long mNativeDicTraverseSession;
|
private long mNativeDicTraverseSession;
|
||||||
|
|
||||||
public DicTraverseSession(Locale locale, long dictionary) {
|
public DicTraverseSession(Locale locale, long dictionary, long dictSize) {
|
||||||
mNativeDicTraverseSession = createNativeDicTraverseSession(
|
mNativeDicTraverseSession = createNativeDicTraverseSession(
|
||||||
locale != null ? locale.toString() : "");
|
locale != null ? locale.toString() : "", dictSize);
|
||||||
initSession(dictionary);
|
initSession(dictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ public final class DicTraverseSession {
|
||||||
mNativeDicTraverseSession, dictionary, previousWord, previousWordLength);
|
mNativeDicTraverseSession, dictionary, previousWord, previousWordLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final long createNativeDicTraverseSession(String locale) {
|
private final long createNativeDicTraverseSession(String locale, long dictSize) {
|
||||||
return setDicTraverseSessionNative(locale);
|
return setDicTraverseSessionNative(locale, dictSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeInternal() {
|
private void closeInternal() {
|
||||||
|
|
|
@ -25,8 +25,9 @@
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
class Dictionary;
|
class Dictionary;
|
||||||
static jlong latinime_setDicTraverseSession(JNIEnv *env, jclass clazz, jstring localeJStr) {
|
static jlong latinime_setDicTraverseSession(JNIEnv *env, jclass clazz, jstring localeJStr,
|
||||||
void *traverseSession = DicTraverseSession::getSessionInstance(env, localeJStr);
|
jlong dictSize) {
|
||||||
|
void *traverseSession = DicTraverseSession::getSessionInstance(env, localeJStr, dictSize);
|
||||||
return reinterpret_cast<jlong>(traverseSession);
|
return reinterpret_cast<jlong>(traverseSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ static void latinime_releaseDicTraverseSession(JNIEnv *env, jclass clazz, jlong
|
||||||
static const JNINativeMethod sMethods[] = {
|
static const JNINativeMethod sMethods[] = {
|
||||||
{
|
{
|
||||||
const_cast<char *>("setDicTraverseSessionNative"),
|
const_cast<char *>("setDicTraverseSessionNative"),
|
||||||
const_cast<char *>("(Ljava/lang/String;)J"),
|
const_cast<char *>("(Ljava/lang/String;J)J"),
|
||||||
reinterpret_cast<void *>(latinime_setDicTraverseSession)
|
reinterpret_cast<void *>(latinime_setDicTraverseSession)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#define MAX_WORD_LENGTH 48
|
#define MAX_WORD_LENGTH 48
|
||||||
// Must be equal to BinaryDictionary.MAX_RESULTS in Java
|
// Must be equal to BinaryDictionary.MAX_RESULTS in Java
|
||||||
#define MAX_RESULTS 18
|
#define MAX_RESULTS 18
|
||||||
// The biggest value among MAX_CACHE_DIC_NODE_SIZE, MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT, ...
|
|
||||||
#define MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY 310
|
|
||||||
// Must be equal to ProximityInfo.MAX_PROXIMITY_CHARS_SIZE in Java
|
// Must be equal to ProximityInfo.MAX_PROXIMITY_CHARS_SIZE in Java
|
||||||
#define MAX_PROXIMITY_CHARS_SIZE 16
|
#define MAX_PROXIMITY_CHARS_SIZE 16
|
||||||
#define ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE 2
|
#define ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE 2
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
|
// The biggest value among MAX_CACHE_DIC_NODE_SIZE, MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT, ...
|
||||||
|
const int DicNodesCache::LARGE_PRIORITY_QUEUE_CAPACITY = 310;
|
||||||
|
// Capacity for reducing memory footprint.
|
||||||
|
const int DicNodesCache::SMALL_PRIORITY_QUEUE_CAPACITY = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Truncates all of the dicNodes so that they start at the given commit point.
|
* Truncates all of the dicNodes so that they start at the given commit point.
|
||||||
* Only called for multi-word typing input.
|
* Only called for multi-word typing input.
|
||||||
|
|
|
@ -31,10 +31,11 @@ class DicNode;
|
||||||
*/
|
*/
|
||||||
class DicNodesCache {
|
class DicNodesCache {
|
||||||
public:
|
public:
|
||||||
AK_FORCE_INLINE DicNodesCache()
|
AK_FORCE_INLINE explicit DicNodesCache(const bool usesLargeCapacityCache)
|
||||||
: mDicNodePriorityQueue0(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
|
: mUsesLargeCapacityCache(usesLargeCapacityCache),
|
||||||
mDicNodePriorityQueue1(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
|
mDicNodePriorityQueue0(getCacheCapacity()),
|
||||||
mDicNodePriorityQueue2(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
|
mDicNodePriorityQueue1(getCacheCapacity()),
|
||||||
|
mDicNodePriorityQueue2(getCacheCapacity()),
|
||||||
mDicNodePriorityQueueForTerminal(MAX_RESULTS),
|
mDicNodePriorityQueueForTerminal(MAX_RESULTS),
|
||||||
mActiveDicNodes(&mDicNodePriorityQueue0),
|
mActiveDicNodes(&mDicNodePriorityQueue0),
|
||||||
mNextActiveDicNodes(&mDicNodePriorityQueue1),
|
mNextActiveDicNodes(&mDicNodePriorityQueue1),
|
||||||
|
@ -50,7 +51,8 @@ class DicNodesCache {
|
||||||
// We want to use the max capacity for the current active dic node queue.
|
// We want to use the max capacity for the current active dic node queue.
|
||||||
mActiveDicNodes->clearAndResizeToCapacity();
|
mActiveDicNodes->clearAndResizeToCapacity();
|
||||||
// nextActiveSize is used to limit the next iteration's active dic node size.
|
// nextActiveSize is used to limit the next iteration's active dic node size.
|
||||||
mNextActiveDicNodes->clearAndResize(nextActiveSize);
|
const int nextActiveSizeFittingToTheCapacity = min(nextActiveSize, getCacheCapacity());
|
||||||
|
mNextActiveDicNodes->clearAndResize(nextActiveSizeFittingToTheCapacity);
|
||||||
mTerminalDicNodes->clearAndResize(terminalSize);
|
mTerminalDicNodes->clearAndResize(terminalSize);
|
||||||
// We want to use the max capacity for the cached dic nodes that will be used for the
|
// We want to use the max capacity for the cached dic nodes that will be used for the
|
||||||
// continuous suggestion.
|
// continuous suggestion.
|
||||||
|
@ -162,12 +164,21 @@ class DicNodesCache {
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AK_FORCE_INLINE int getCacheCapacity() const {
|
||||||
|
return mUsesLargeCapacityCache ?
|
||||||
|
LARGE_PRIORITY_QUEUE_CAPACITY : SMALL_PRIORITY_QUEUE_CAPACITY;
|
||||||
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE void resetTemporaryCaches() {
|
AK_FORCE_INLINE void resetTemporaryCaches() {
|
||||||
mActiveDicNodes->clear();
|
mActiveDicNodes->clear();
|
||||||
mNextActiveDicNodes->clear();
|
mNextActiveDicNodes->clear();
|
||||||
mTerminalDicNodes->clear();
|
mTerminalDicNodes->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const int LARGE_PRIORITY_QUEUE_CAPACITY;
|
||||||
|
static const int SMALL_PRIORITY_QUEUE_CAPACITY;
|
||||||
|
|
||||||
|
const bool mUsesLargeCapacityCache;
|
||||||
// Instances
|
// Instances
|
||||||
DicNodePriorityQueue mDicNodePriorityQueue0;
|
DicNodePriorityQueue mDicNodePriorityQueue0;
|
||||||
DicNodePriorityQueue mDicNodePriorityQueue1;
|
DicNodePriorityQueue mDicNodePriorityQueue1;
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
|
// 256K bytes threshold is heuristically used to distinguish dictionaries containing many unigrams
|
||||||
|
// (e.g. main dictionary) from small dictionaries (e.g. contacts...)
|
||||||
|
const int DicTraverseSession::DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION =
|
||||||
|
256 * 1024;
|
||||||
|
|
||||||
void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
|
void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
|
||||||
int prevWordLength, const SuggestOptions *const suggestOptions) {
|
int prevWordLength, const SuggestOptions *const suggestOptions) {
|
||||||
mDictionary = dictionary;
|
mDictionary = dictionary;
|
||||||
|
|
|
@ -37,8 +37,12 @@ class DicTraverseSession {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// A factory method for DicTraverseSession
|
// A factory method for DicTraverseSession
|
||||||
static AK_FORCE_INLINE void *getSessionInstance(JNIEnv *env, jstring localeStr) {
|
static AK_FORCE_INLINE void *getSessionInstance(JNIEnv *env, jstring localeStr,
|
||||||
return new DicTraverseSession(env, localeStr);
|
jlong dictSize) {
|
||||||
|
// To deal with the trade-off between accuracy and memory space, large cache is used for
|
||||||
|
// dictionaries larger that the threshold
|
||||||
|
return new DicTraverseSession(env, localeStr,
|
||||||
|
dictSize >= DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AK_FORCE_INLINE void initSessionInstance(DicTraverseSession *traverseSession,
|
static AK_FORCE_INLINE void initSessionInstance(DicTraverseSession *traverseSession,
|
||||||
|
@ -54,10 +58,10 @@ class DicTraverseSession {
|
||||||
delete traverseSession;
|
delete traverseSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr)
|
AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache)
|
||||||
: mPrevWordPos(NOT_A_VALID_WORD_POS), mProximityInfo(0),
|
: mPrevWordPos(NOT_A_VALID_WORD_POS), mProximityInfo(0),
|
||||||
mDictionary(0), mSuggestOptions(0), mDicNodesCache(), mMultiBigramMap(),
|
mDictionary(0), mSuggestOptions(0), mDicNodesCache(usesLargeCache),
|
||||||
mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
|
mMultiBigramMap(), mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
|
||||||
mMultiWordCostMultiplier(1.0f) {
|
mMultiWordCostMultiplier(1.0f) {
|
||||||
// NOTE: mProximityInfoStates is an array of instances.
|
// NOTE: mProximityInfoStates is an array of instances.
|
||||||
// No need to initialize it explicitly here.
|
// No need to initialize it explicitly here.
|
||||||
|
@ -181,6 +185,7 @@ class DicTraverseSession {
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
|
||||||
// threshold to start caching
|
// threshold to start caching
|
||||||
static const int CACHE_START_INPUT_LENGTH_THRESHOLD;
|
static const int CACHE_START_INPUT_LENGTH_THRESHOLD;
|
||||||
|
static const int DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION;
|
||||||
void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs,
|
void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs,
|
||||||
const int *const inputYs, const int *const times, const int *const pointerIds,
|
const int *const inputYs, const int *const times, const int *const pointerIds,
|
||||||
const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
|
const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
|
||||||
|
|
Loading…
Reference in New Issue