use separate locks for nodes/ways/areas render instructions cache
This commit is contained in:
parent
bb39069af2
commit
836f0ea82b
@ -28,7 +28,7 @@ import android.graphics.Color;
|
|||||||
* A RenderTheme defines how ways and nodes are drawn.
|
* A RenderTheme defines how ways and nodes are drawn.
|
||||||
*/
|
*/
|
||||||
public class RenderTheme {
|
public class RenderTheme {
|
||||||
private final static String TAG = RenderTheme.class.getName();
|
//private final static String TAG = RenderTheme.class.getName();
|
||||||
|
|
||||||
private static final int MATCHING_CACHE_SIZE = 512;
|
private static final int MATCHING_CACHE_SIZE = 512;
|
||||||
private static final int RENDER_THEME_VERSION = 1;
|
private static final int RENDER_THEME_VERSION = 1;
|
||||||
@ -84,9 +84,17 @@ public class RenderTheme {
|
|||||||
private final int mMapBackground;
|
private final int mMapBackground;
|
||||||
private final ArrayList<Rule> mRulesList;
|
private final ArrayList<Rule> mRulesList;
|
||||||
|
|
||||||
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mMatchingCacheNodes;
|
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mNodesCache;
|
||||||
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mMatchingCacheWay;
|
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mWayCache;
|
||||||
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mMatchingCacheArea;
|
private final LRUCache<MatchingCacheKey, RenderInstructionItem> mAreaCache;
|
||||||
|
|
||||||
|
private MatchingCacheKey mAreaCacheKey = new MatchingCacheKey();
|
||||||
|
private MatchingCacheKey mWayCacheKey = new MatchingCacheKey();
|
||||||
|
private MatchingCacheKey mNodeCacheKey = new MatchingCacheKey();
|
||||||
|
|
||||||
|
private ArrayList<RenderInstruction> mWayInstructionList = new ArrayList<RenderInstruction>(4);
|
||||||
|
private ArrayList<RenderInstruction> mAreaInstructionList = new ArrayList<RenderInstruction>(4);
|
||||||
|
private ArrayList<RenderInstruction> mNodeInstructionList = new ArrayList<RenderInstruction>(4);
|
||||||
|
|
||||||
class RenderInstructionItem {
|
class RenderInstructionItem {
|
||||||
RenderInstructionItem next;
|
RenderInstructionItem next;
|
||||||
@ -100,11 +108,11 @@ public class RenderTheme {
|
|||||||
mBaseTextSize = baseTextSize;
|
mBaseTextSize = baseTextSize;
|
||||||
mRulesList = new ArrayList<Rule>();
|
mRulesList = new ArrayList<Rule>();
|
||||||
|
|
||||||
mMatchingCacheNodes = new LRUCache<MatchingCacheKey, RenderInstructionItem>(
|
mNodesCache = new LRUCache<MatchingCacheKey, RenderInstructionItem>(
|
||||||
MATCHING_CACHE_SIZE);
|
MATCHING_CACHE_SIZE);
|
||||||
mMatchingCacheWay = new LRUCache<MatchingCacheKey, RenderInstructionItem>(
|
mWayCache = new LRUCache<MatchingCacheKey, RenderInstructionItem>(
|
||||||
MATCHING_CACHE_SIZE);
|
MATCHING_CACHE_SIZE);
|
||||||
mMatchingCacheArea = new LRUCache<MatchingCacheKey, RenderInstructionItem>(
|
mAreaCache = new LRUCache<MatchingCacheKey, RenderInstructionItem>(
|
||||||
MATCHING_CACHE_SIZE);
|
MATCHING_CACHE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,9 +121,9 @@ public class RenderTheme {
|
|||||||
* resources.
|
* resources.
|
||||||
*/
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
mMatchingCacheNodes.clear();
|
mNodesCache.clear();
|
||||||
mMatchingCacheArea.clear();
|
mAreaCache.clear();
|
||||||
mMatchingCacheWay.clear();
|
mWayCache.clear();
|
||||||
|
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
for (int i = 0, n = mRulesList.size(); i < n; ++i) {
|
||||||
mRulesList.get(i).onDestroy();
|
mRulesList.get(i).onDestroy();
|
||||||
@ -153,7 +161,7 @@ public class RenderTheme {
|
|||||||
* ...
|
* ...
|
||||||
* @return ...
|
* @return ...
|
||||||
*/
|
*/
|
||||||
public synchronized RenderInstruction[] matchNode(IRenderCallback renderCallback,
|
public RenderInstruction[] matchNode(IRenderCallback renderCallback,
|
||||||
Tag[] tags, byte zoomLevel) {
|
Tag[] tags, byte zoomLevel) {
|
||||||
|
|
||||||
// list of renderinsctruction items in cache
|
// list of renderinsctruction items in cache
|
||||||
@ -162,75 +170,77 @@ public class RenderTheme {
|
|||||||
// the item matching tags and zoomlevel
|
// the item matching tags and zoomlevel
|
||||||
RenderInstructionItem ri = null;
|
RenderInstructionItem ri = null;
|
||||||
|
|
||||||
MatchingCacheKey matchingCacheKey = new MatchingCacheKey(tags);
|
synchronized (mNodesCache) {
|
||||||
boolean found = mMatchingCacheNodes.containsKey(matchingCacheKey);
|
MatchingCacheKey cacheKey = mNodeCacheKey; //new MatchingCacheKey(tags);
|
||||||
int zoomMask = 1 << zoomLevel;
|
cacheKey.set(tags);
|
||||||
|
boolean found = mNodesCache.containsKey(cacheKey);
|
||||||
|
int zoomMask = 1 << zoomLevel;
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
ris = mMatchingCacheNodes.get(matchingCacheKey);
|
ris = mNodesCache.get(cacheKey);
|
||||||
|
|
||||||
for (ri = ris; ri != null; ri = ri.next)
|
for (ri = ris; ri != null; ri = ri.next)
|
||||||
if ((ri.zoom & zoomMask) != 0)
|
if ((ri.zoom & zoomMask) != 0)
|
||||||
// cache hit
|
// cache hit
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ri == null) {
|
if (ri == null) {
|
||||||
// cache miss
|
// cache miss
|
||||||
List<RenderInstruction> matches = mMatchingList;
|
List<RenderInstruction> matches = mNodeInstructionList;
|
||||||
matches.clear();
|
matches.clear();
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i)
|
for (int i = 0, n = mRulesList.size(); i < n; ++i)
|
||||||
mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel, matches);
|
mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel, matches);
|
||||||
|
|
||||||
int size = matches.size();
|
int size = matches.size();
|
||||||
|
|
||||||
// check if same instructions are used in another level
|
// check if same instructions are used in another level
|
||||||
for (ri = ris; ri != null; ri = ri.next) {
|
for (ri = ris; ri != null; ri = ri.next) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
if (ri.list != null)
|
if (ri.list != null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// both matchinglists are empty
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ri.list == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// both matchinglists are empty
|
if (ri.list.length != size)
|
||||||
break;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (ri.list == null)
|
int i = 0;
|
||||||
continue;
|
for (RenderInstruction r : ri.list) {
|
||||||
|
if (r != matches.get(i))
|
||||||
if (ri.list.length != size)
|
break;
|
||||||
continue;
|
i++;
|
||||||
|
}
|
||||||
int i = 0;
|
if (i == size)
|
||||||
for (RenderInstruction r : ri.list) {
|
// both matching lists contain the same items
|
||||||
if (r != matches.get(i))
|
|
||||||
break;
|
break;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
if (i == size)
|
|
||||||
// both matching lists contain the same items
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ri != null) {
|
if (ri != null) {
|
||||||
// we found a same matchting list on another zoomlevel
|
// we found a same matchting list on another zoomlevel
|
||||||
ri.zoom |= zoomMask;
|
ri.zoom |= zoomMask;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ri = new RenderInstructionItem();
|
ri = new RenderInstructionItem();
|
||||||
ri.zoom = zoomMask;
|
ri.zoom = zoomMask;
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
ri.list = new RenderInstruction[size];
|
ri.list = new RenderInstruction[size];
|
||||||
matches.toArray(ri.list);
|
matches.toArray(ri.list);
|
||||||
|
}
|
||||||
|
// attach this list to the one found for MatchingKey
|
||||||
|
if (ris != null)
|
||||||
|
ris.next = ri;
|
||||||
|
else
|
||||||
|
mNodesCache.put(new MatchingCacheKey(cacheKey), ri);
|
||||||
}
|
}
|
||||||
// attach this list to the one found for MatchingKey
|
|
||||||
if (ris != null)
|
|
||||||
ris.next = ri;
|
|
||||||
else
|
|
||||||
mMatchingCacheNodes.put(matchingCacheKey, ri);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ri.list != null)
|
if (ri.list != null)
|
||||||
render(renderCallback, ri.list, tags);
|
render(renderCallback, ri.list, tags);
|
||||||
|
|
||||||
@ -238,10 +248,8 @@ public class RenderTheme {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int missCnt = 0;
|
//private int missCnt = 0;
|
||||||
private int hitCnt = 0;
|
//private int hitCnt = 0;
|
||||||
private MatchingCacheKey mCacheKey = new MatchingCacheKey();
|
|
||||||
private ArrayList<RenderInstruction> mMatchingList = new ArrayList<RenderInstruction>(4);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches a way with the given parameters against this RenderTheme.
|
* Matches a way with the given parameters against this RenderTheme.
|
||||||
@ -258,7 +266,7 @@ public class RenderTheme {
|
|||||||
* ...
|
* ...
|
||||||
* @return currently processed render instructions
|
* @return currently processed render instructions
|
||||||
*/
|
*/
|
||||||
public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback,
|
public RenderInstruction[] matchWay(IRenderCallback renderCallback,
|
||||||
Tag[] tags, byte zoomLevel, boolean closed, boolean render) {
|
Tag[] tags, byte zoomLevel, boolean closed, boolean render) {
|
||||||
|
|
||||||
// list of renderinsctruction items in cache
|
// list of renderinsctruction items in cache
|
||||||
@ -266,90 +274,95 @@ public class RenderTheme {
|
|||||||
|
|
||||||
// the item matching tags and zoomlevel
|
// the item matching tags and zoomlevel
|
||||||
RenderInstructionItem ri = null;
|
RenderInstructionItem ri = null;
|
||||||
|
List<RenderInstruction> matches;
|
||||||
|
|
||||||
LRUCache<MatchingCacheKey, RenderInstructionItem> matchingCache;
|
LRUCache<MatchingCacheKey, RenderInstructionItem> matchingCache;
|
||||||
MatchingCacheKey matchingCacheKey;
|
MatchingCacheKey cacheKey;
|
||||||
|
|
||||||
if (closed) {
|
if (closed) {
|
||||||
matchingCache = mMatchingCacheArea;
|
matchingCache = mAreaCache;
|
||||||
|
cacheKey = mAreaCacheKey;
|
||||||
|
matches = mAreaInstructionList;
|
||||||
} else {
|
} else {
|
||||||
matchingCache = mMatchingCacheWay;
|
matchingCache = mWayCache;
|
||||||
|
cacheKey = mWayCacheKey;
|
||||||
|
matches = mWayInstructionList;
|
||||||
}
|
}
|
||||||
int zoomMask = 1 << zoomLevel;
|
int zoomMask = 1 << zoomLevel;
|
||||||
|
|
||||||
mCacheKey.set(tags);
|
synchronized (matchingCache) {
|
||||||
ris = matchingCache.get(mCacheKey);
|
cacheKey.set(tags);
|
||||||
|
ris = matchingCache.get(cacheKey);
|
||||||
|
|
||||||
for (ri = ris; ri != null; ri = ri.next)
|
for (ri = ris; ri != null; ri = ri.next)
|
||||||
if ((ri.zoom & zoomMask) != 0)
|
if ((ri.zoom & zoomMask) != 0)
|
||||||
// cache hit
|
// cache hit
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ri == null) {
|
if (ri == null) {
|
||||||
// cache miss
|
// cache miss
|
||||||
//Log.d(TAG, missCnt++ + " / " + hitCnt + " Cache Miss");
|
//Log.d(TAG, missCnt++ + " / " + hitCnt + " Cache Miss");
|
||||||
|
|
||||||
int c = (closed ? Closed.YES : Closed.NO);
|
int c = (closed ? Closed.YES : Closed.NO);
|
||||||
List<RenderInstruction> matches = mMatchingList;
|
//List<RenderInstruction> matches = mMatchingList;
|
||||||
matches.clear();
|
matches.clear();
|
||||||
|
|
||||||
for (int i = 0, n = mRulesList.size(); i < n; ++i)
|
for (int i = 0, n = mRulesList.size(); i < n; ++i)
|
||||||
mRulesList.get(i).matchWay(renderCallback, tags, zoomLevel, c, matches);
|
mRulesList.get(i).matchWay(renderCallback, tags, zoomLevel, c, matches);
|
||||||
|
|
||||||
int size = matches.size();
|
int size = matches.size();
|
||||||
// check if same instructions are used in another level
|
// check if same instructions are used in another level
|
||||||
for (ri = ris; ri != null; ri = ri.next) {
|
for (ri = ris; ri != null; ri = ri.next) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
if (ri.list != null)
|
if (ri.list != null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// both matchinglists are empty
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ri.list == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// both matchinglists are empty
|
if (ri.list.length != size)
|
||||||
break;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (ri.list == null)
|
int i = 0;
|
||||||
continue;
|
for (RenderInstruction r : ri.list) {
|
||||||
|
if (r != matches.get(i))
|
||||||
if (ri.list.length != size)
|
break;
|
||||||
continue;
|
i++;
|
||||||
|
}
|
||||||
int i = 0;
|
if (i == size)
|
||||||
for (RenderInstruction r : ri.list) {
|
// both matching lists contain the same items
|
||||||
if (r != matches.get(i))
|
|
||||||
break;
|
break;
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i == size)
|
|
||||||
// both matching lists contain the same items
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ri != null) {
|
|
||||||
// we found a same matchting list on another zoomlevel
|
|
||||||
ri.zoom |= zoomMask;
|
|
||||||
//Log.d(TAG, " same instructions " + size + " " + Arrays.deepToString(tags));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//Log.d(TAG, " new instructions " + size + " " + Arrays.deepToString(tags));
|
|
||||||
|
|
||||||
ri = new RenderInstructionItem();
|
|
||||||
ri.zoom = zoomMask;
|
|
||||||
|
|
||||||
if (size > 0) {
|
|
||||||
ri.list = new RenderInstruction[size];
|
|
||||||
matches.toArray(ri.list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// attach this list to the one found for MatchingKey
|
if (ri != null) {
|
||||||
if (ris != null) {
|
// we found a same matchting list on another zoomlevel
|
||||||
ris.next = ri;
|
ri.zoom |= zoomMask;
|
||||||
}
|
//Log.d(TAG, " same instructions " + size + " " + Arrays.deepToString(tags));
|
||||||
else {
|
|
||||||
matchingCacheKey = new MatchingCacheKey(mCacheKey);
|
} else {
|
||||||
matchingCache.put(matchingCacheKey, ri);
|
//Log.d(TAG, " new instructions " + size + " " + Arrays.deepToString(tags));
|
||||||
|
|
||||||
|
ri = new RenderInstructionItem();
|
||||||
|
ri.zoom = zoomMask;
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
ri.list = new RenderInstruction[size];
|
||||||
|
matches.toArray(ri.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// attach this list to the one found for MatchingKey
|
||||||
|
if (ris != null) {
|
||||||
|
ris.next = ri;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
matchingCache.put(new MatchingCacheKey(cacheKey), ri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (render && ri.list != null) {
|
if (render && ri.list != null) {
|
||||||
for (int i = 0, n = ri.list.length; i < n; i++)
|
for (int i = 0, n = ri.list.length; i < n; i++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user