Make terminal cache small.
Bug: 10699291 Before: (0) 2997.63 (0.98%) (1) 303760.77 (98.92%) (2) 274.94 (0.09%) (66) 0.38 (0.00%) Total 307062.27 (sum of others 307033.73) After: (0) 2953.22 (0.96%) (1) 304633.86 (98.93%) (2) 293.76 (0.10%) (66) 0.38 (0.00%) Total 307915.65 (sum of others 307881.22) Change-Id: I6905abeb590ef50d48ddfcd8ef8b5351af399150main
parent
d7b7698499
commit
80ca7abea3
|
@ -32,6 +32,8 @@
|
||||||
#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
|
||||||
|
@ -322,13 +324,6 @@ static inline void prof_out(void) {
|
||||||
#define MAX_POINTER_COUNT 1
|
#define MAX_POINTER_COUNT 1
|
||||||
#define MAX_POINTER_COUNT_G 2
|
#define MAX_POINTER_COUNT_G 2
|
||||||
|
|
||||||
// Queue IDs and size for DicNodesCache
|
|
||||||
#define DIC_NODES_CACHE_INITIAL_QUEUE_ID_ACTIVE 0
|
|
||||||
#define DIC_NODES_CACHE_INITIAL_QUEUE_ID_NEXT_ACTIVE 1
|
|
||||||
#define DIC_NODES_CACHE_INITIAL_QUEUE_ID_TERMINAL 2
|
|
||||||
#define DIC_NODES_CACHE_INITIAL_QUEUE_ID_CACHE_FOR_CONTINUOUS_SUGGESTION 3
|
|
||||||
#define DIC_NODES_CACHE_PRIORITY_QUEUES_SIZE 4
|
|
||||||
|
|
||||||
template<typename T> AK_FORCE_INLINE const T &min(const T &a, const T &b) { return a < b ? a : b; }
|
template<typename T> AK_FORCE_INLINE const T &min(const T &a, const T &b) { return a < b ? a : b; }
|
||||||
template<typename T> AK_FORCE_INLINE const T &max(const T &a, const T &b) { return a > b ? a : b; }
|
template<typename T> AK_FORCE_INLINE const T &max(const T &a, const T &b) { return a > b ? a : b; }
|
||||||
|
|
||||||
|
|
|
@ -24,20 +24,16 @@
|
||||||
#include "suggest/core/dicnode/dic_node.h"
|
#include "suggest/core/dicnode/dic_node.h"
|
||||||
#include "suggest/core/dicnode/dic_node_release_listener.h"
|
#include "suggest/core/dicnode/dic_node_release_listener.h"
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
class DicNodePriorityQueue : public DicNodeReleaseListener {
|
class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
public:
|
public:
|
||||||
AK_FORCE_INLINE DicNodePriorityQueue()
|
AK_FORCE_INLINE explicit DicNodePriorityQueue(const int capacity)
|
||||||
: MAX_CAPACITY(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
|
: mCapacity(capacity), mMaxSize(capacity), mDicNodesBuf(),
|
||||||
mMaxSize(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY), mDicNodesBuf(), mUnusedNodeIndices(),
|
mUnusedNodeIndices(), mNextUnusedNodeId(0), mDicNodesQueue() {
|
||||||
mNextUnusedNodeId(0), mDicNodesQueue() {
|
mDicNodesBuf.resize(mCapacity + 1);
|
||||||
mDicNodesBuf.resize(MAX_CAPACITY + 1);
|
mUnusedNodeIndices.resize(mCapacity + 1);
|
||||||
mUnusedNodeIndices.resize(MAX_CAPACITY + 1);
|
clearAndResizeToCapacity();
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non virtual inline destructor -- never inherit this class
|
// Non virtual inline destructor -- never inherit this class
|
||||||
|
@ -52,11 +48,12 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE void setMaxSize(const int maxSize) {
|
AK_FORCE_INLINE void setMaxSize(const int maxSize) {
|
||||||
mMaxSize = min(maxSize, MAX_CAPACITY);
|
ASSERT(maxSize <= mCapacity);
|
||||||
|
mMaxSize = min(maxSize, mCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE void reset() {
|
AK_FORCE_INLINE void clearAndResizeToCapacity() {
|
||||||
clearAndResize(MAX_CAPACITY);
|
clearAndResize(mCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE void clear() {
|
AK_FORCE_INLINE void clear() {
|
||||||
|
@ -64,27 +61,19 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE void clearAndResize(const int maxSize) {
|
AK_FORCE_INLINE void clearAndResize(const int maxSize) {
|
||||||
|
ASSERT(maxSize <= mCapacity);
|
||||||
while (!mDicNodesQueue.empty()) {
|
while (!mDicNodesQueue.empty()) {
|
||||||
mDicNodesQueue.pop();
|
mDicNodesQueue.pop();
|
||||||
}
|
}
|
||||||
setMaxSize(maxSize);
|
setMaxSize(maxSize);
|
||||||
for (int i = 0; i < MAX_CAPACITY + 1; ++i) {
|
for (int i = 0; i < mCapacity + 1; ++i) {
|
||||||
mDicNodesBuf[i].remove();
|
mDicNodesBuf[i].remove();
|
||||||
mDicNodesBuf[i].setReleaseListener(this);
|
mDicNodesBuf[i].setReleaseListener(this);
|
||||||
mUnusedNodeIndices[i] = i == MAX_CAPACITY ? NOT_A_NODE_ID : static_cast<int>(i) + 1;
|
mUnusedNodeIndices[i] = i == mCapacity ? NOT_A_NODE_ID : static_cast<int>(i) + 1;
|
||||||
}
|
}
|
||||||
mNextUnusedNodeId = 0;
|
mNextUnusedNodeId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE DicNode *newDicNode(DicNode *dicNode) {
|
|
||||||
DicNode *newNode = searchEmptyDicNode();
|
|
||||||
if (newNode) {
|
|
||||||
DicNodeUtils::initByCopy(dicNode, newNode);
|
|
||||||
return newNode;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy
|
// Copy
|
||||||
AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode) {
|
AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode) {
|
||||||
return copyPush(dicNode, mMaxSize);
|
return copyPush(dicNode, mMaxSize);
|
||||||
|
@ -111,12 +100,12 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
}
|
}
|
||||||
mUnusedNodeIndices[index] = mNextUnusedNodeId;
|
mUnusedNodeIndices[index] = mNextUnusedNodeId;
|
||||||
mNextUnusedNodeId = index;
|
mNextUnusedNodeId = index;
|
||||||
ASSERT(index >= 0 && index < (MAX_CAPACITY + 1));
|
ASSERT(index >= 0 && index < (mCapacity + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE void dump() const {
|
AK_FORCE_INLINE void dump() const {
|
||||||
AKLOGI("\n\n\n\n\n===========================");
|
AKLOGI("\n\n\n\n\n===========================");
|
||||||
for (int i = 0; i < MAX_CAPACITY + 1; ++i) {
|
for (int i = 0; i < mCapacity + 1; ++i) {
|
||||||
if (mDicNodesBuf[i].isUsed()) {
|
if (mDicNodesBuf[i].isUsed()) {
|
||||||
mDicNodesBuf[i].dump("QUEUE: ");
|
mDicNodesBuf[i].dump("QUEUE: ");
|
||||||
}
|
}
|
||||||
|
@ -125,7 +114,7 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(DicNodePriorityQueue);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue);
|
||||||
static const int NOT_A_NODE_ID = -1;
|
static const int NOT_A_NODE_ID = -1;
|
||||||
|
|
||||||
AK_FORCE_INLINE static bool compareDicNode(DicNode *left, DicNode *right) {
|
AK_FORCE_INLINE static bool compareDicNode(DicNode *left, DicNode *right) {
|
||||||
|
@ -139,7 +128,7 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
|
typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
|
||||||
const int MAX_CAPACITY;
|
const int mCapacity;
|
||||||
int mMaxSize;
|
int mMaxSize;
|
||||||
std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively
|
std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively
|
||||||
std::vector<int> mUnusedNodeIndices;
|
std::vector<int> mUnusedNodeIndices;
|
||||||
|
@ -163,13 +152,12 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE DicNode *searchEmptyDicNode() {
|
AK_FORCE_INLINE DicNode *searchEmptyDicNode() {
|
||||||
// TODO: Currently O(n) but should be improved to O(1)
|
if (mCapacity == 0) {
|
||||||
if (MAX_CAPACITY == 0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (mNextUnusedNodeId == NOT_A_NODE_ID) {
|
if (mNextUnusedNodeId == NOT_A_NODE_ID) {
|
||||||
AKLOGI("No unused node found.");
|
AKLOGI("No unused node found.");
|
||||||
for (int i = 0; i < MAX_CAPACITY + 1; ++i) {
|
for (int i = 0; i < mCapacity + 1; ++i) {
|
||||||
AKLOGI("Dump node availability, %d, %d, %d",
|
AKLOGI("Dump node availability, %d, %d, %d",
|
||||||
i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]);
|
i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]);
|
||||||
}
|
}
|
||||||
|
@ -185,7 +173,7 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
|
const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
|
||||||
mNextUnusedNodeId = mUnusedNodeIndices[index];
|
mNextUnusedNodeId = mUnusedNodeIndices[index];
|
||||||
mUnusedNodeIndices[index] = NOT_A_NODE_ID;
|
mUnusedNodeIndices[index] = NOT_A_NODE_ID;
|
||||||
ASSERT(index >= 0 && index < (MAX_CAPACITY + 1));
|
ASSERT(index >= 0 && index < (mCapacity + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) {
|
AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) {
|
||||||
|
@ -209,6 +197,15 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
|
||||||
AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode, const int maxSize) {
|
AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode, const int maxSize) {
|
||||||
return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize);
|
return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AK_FORCE_INLINE DicNode *newDicNode(DicNode *dicNode) {
|
||||||
|
DicNode *newNode = searchEmptyDicNode();
|
||||||
|
if (newNode) {
|
||||||
|
DicNodeUtils::initByCopy(dicNode, newNode);
|
||||||
|
}
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
} // namespace latinime
|
} // namespace latinime
|
||||||
#endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
|
#endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
|
||||||
|
|
|
@ -32,24 +32,29 @@ class DicNode;
|
||||||
class DicNodesCache {
|
class DicNodesCache {
|
||||||
public:
|
public:
|
||||||
AK_FORCE_INLINE DicNodesCache()
|
AK_FORCE_INLINE DicNodesCache()
|
||||||
: mActiveDicNodes(&mDicNodePriorityQueues[DIC_NODES_CACHE_INITIAL_QUEUE_ID_ACTIVE]),
|
: mDicNodePriorityQueue0(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
|
||||||
mNextActiveDicNodes(&mDicNodePriorityQueues[
|
mDicNodePriorityQueue1(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
|
||||||
DIC_NODES_CACHE_INITIAL_QUEUE_ID_NEXT_ACTIVE]),
|
mDicNodePriorityQueue2(MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY),
|
||||||
mTerminalDicNodes(&mDicNodePriorityQueues[DIC_NODES_CACHE_INITIAL_QUEUE_ID_TERMINAL]),
|
mDicNodePriorityQueueForTerminal(MAX_RESULTS),
|
||||||
mCachedDicNodesForContinuousSuggestion(&mDicNodePriorityQueues[
|
mActiveDicNodes(&mDicNodePriorityQueue0),
|
||||||
DIC_NODES_CACHE_INITIAL_QUEUE_ID_CACHE_FOR_CONTINUOUS_SUGGESTION]),
|
mNextActiveDicNodes(&mDicNodePriorityQueue1),
|
||||||
mInputIndex(0), mLastCachedInputIndex(0) {
|
mCachedDicNodesForContinuousSuggestion(&mDicNodePriorityQueue2),
|
||||||
}
|
mTerminalDicNodes(&mDicNodePriorityQueueForTerminal),
|
||||||
|
mInputIndex(0), mLastCachedInputIndex(0) {}
|
||||||
|
|
||||||
AK_FORCE_INLINE virtual ~DicNodesCache() {}
|
AK_FORCE_INLINE virtual ~DicNodesCache() {}
|
||||||
|
|
||||||
AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) {
|
AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) {
|
||||||
mInputIndex = 0;
|
mInputIndex = 0;
|
||||||
mLastCachedInputIndex = 0;
|
mLastCachedInputIndex = 0;
|
||||||
mActiveDicNodes->reset();
|
// We want to use the max capacity for the current active dic node queue.
|
||||||
|
mActiveDicNodes->clearAndResizeToCapacity();
|
||||||
|
// nextActiveSize is used to limit the next iteration's active dic node size.
|
||||||
mNextActiveDicNodes->clearAndResize(nextActiveSize);
|
mNextActiveDicNodes->clearAndResize(nextActiveSize);
|
||||||
mTerminalDicNodes->clearAndResize(terminalSize);
|
mTerminalDicNodes->clearAndResize(terminalSize);
|
||||||
mCachedDicNodesForContinuousSuggestion->reset();
|
// We want to use the max capacity for the cached dic nodes that will be used for the
|
||||||
|
// continuous suggestion.
|
||||||
|
mCachedDicNodesForContinuousSuggestion->clearAndResizeToCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_FORCE_INLINE void continueSearch() {
|
AK_FORCE_INLINE void continueSearch() {
|
||||||
|
@ -163,15 +168,20 @@ class DicNodesCache {
|
||||||
mTerminalDicNodes->clear();
|
mTerminalDicNodes->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
DicNodePriorityQueue mDicNodePriorityQueues[DIC_NODES_CACHE_PRIORITY_QUEUES_SIZE];
|
// Instances
|
||||||
|
DicNodePriorityQueue mDicNodePriorityQueue0;
|
||||||
|
DicNodePriorityQueue mDicNodePriorityQueue1;
|
||||||
|
DicNodePriorityQueue mDicNodePriorityQueue2;
|
||||||
|
DicNodePriorityQueue mDicNodePriorityQueueForTerminal;
|
||||||
|
|
||||||
// Active dicNodes currently being expanded.
|
// Active dicNodes currently being expanded.
|
||||||
DicNodePriorityQueue *mActiveDicNodes;
|
DicNodePriorityQueue *mActiveDicNodes;
|
||||||
// Next dicNodes to be expanded.
|
// Next dicNodes to be expanded.
|
||||||
DicNodePriorityQueue *mNextActiveDicNodes;
|
DicNodePriorityQueue *mNextActiveDicNodes;
|
||||||
// Current top terminal dicNodes.
|
|
||||||
DicNodePriorityQueue *mTerminalDicNodes;
|
|
||||||
// Cached dicNodes used for continuous suggestion.
|
// Cached dicNodes used for continuous suggestion.
|
||||||
DicNodePriorityQueue *mCachedDicNodesForContinuousSuggestion;
|
DicNodePriorityQueue *mCachedDicNodesForContinuousSuggestion;
|
||||||
|
// Current top terminal dicNodes.
|
||||||
|
DicNodePriorityQueue *mTerminalDicNodes;
|
||||||
int mInputIndex;
|
int mInputIndex;
|
||||||
int mLastCachedInputIndex;
|
int mLastCachedInputIndex;
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,8 +59,9 @@ const DictionaryStructureWithBufferPolicy *DicTraverseSession::getDictionaryStru
|
||||||
return mDictionary->getDictionaryStructurePolicy();
|
return mDictionary->getDictionaryStructurePolicy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DicTraverseSession::resetCache(const int nextActiveCacheSize, const int maxWords) {
|
void DicTraverseSession::resetCache(const int thresholdForNextActiveDicNodes, const int maxWords) {
|
||||||
mDicNodesCache.reset(nextActiveCacheSize, maxWords);
|
mDicNodesCache.reset(thresholdForNextActiveDicNodes /* nextActiveSize */,
|
||||||
|
maxWords /* terminalSize */);
|
||||||
mMultiBigramMap.clear();
|
mMultiBigramMap.clear();
|
||||||
mPartiallyCommited = false;
|
mPartiallyCommited = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ class DicTraverseSession {
|
||||||
const int inputSize, const int *const inputXs, const int *const inputYs,
|
const int inputSize, const int *const inputXs, const int *const inputYs,
|
||||||
const int *const times, const int *const pointerIds, const float maxSpatialDistance,
|
const int *const times, const int *const pointerIds, const float maxSpatialDistance,
|
||||||
const int maxPointerCount);
|
const int maxPointerCount);
|
||||||
void resetCache(const int nextActiveCacheSize, const int maxWords);
|
void resetCache(const int thresholdForNextActiveDicNodes, const int maxWords);
|
||||||
|
|
||||||
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const;
|
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue