use specialized BinarySort for MapTiles that also repacks the 'sparsed' array

This commit is contained in:
Hannes Janetzek 2013-01-07 01:24:35 +01:00
parent ec647fc4f5
commit 9d2ebab088
4 changed files with 124 additions and 62 deletions

View File

@ -17,8 +17,6 @@ package org.oscim.generator;
import static org.oscim.generator.JobTile.STATE_LOADING; import static org.oscim.generator.JobTile.STATE_LOADING;
import static org.oscim.generator.JobTile.STATE_NONE; import static org.oscim.generator.JobTile.STATE_NONE;
import java.util.Arrays;
/** /**
* A JobQueue keeps the list of pending jobs for a MapView and prioritizes them. * A JobQueue keeps the list of pending jobs for a MapView and prioritizes them.
*/ */
@ -71,8 +69,12 @@ public class JobQueue {
if (mJobs == null) if (mJobs == null)
return null; return null;
if (mCurrentJob == 0) if (mCurrentJob == 0) {
Arrays.sort(mJobs); //Arrays.sort(mJobs);
int len = mJobs.length;
if (len > 1)
TileDistanceSort.sort(mJobs, 0, len);
}
//return mPriorityQueue.poll(); //return mPriorityQueue.poll();
JobTile t = mJobs[mCurrentJob]; JobTile t = mJobs[mCurrentJob];

View File

@ -21,7 +21,7 @@ import android.util.Log;
/** /**
* @author Hannes Janetzek * @author Hannes Janetzek
*/ */
public class JobTile extends Tile implements Comparable<JobTile> { public class JobTile extends Tile {
private final static String TAG = JobTile.class.getName(); private final static String TAG = JobTile.class.getName();
public final static int STATE_NONE = 0; public final static int STATE_NONE = 0;
@ -59,15 +59,4 @@ public class JobTile extends Tile implements Comparable<JobTile> {
public JobTile(int tileX, int tileY, byte zoomLevel) { public JobTile(int tileX, int tileY, byte zoomLevel) {
super(tileX, tileY, zoomLevel); super(tileX, tileY, zoomLevel);
} }
@Override
public int compareTo(JobTile o) {
if (this.distance < o.distance) {
return -1;
}
if (this.distance > o.distance) {
return 1;
}
return 0;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2010, 2011, 2012 mapsforge.org * Copyright 2013 OpenScienceMap
* *
* This program is free software: you can redistribute it and/or modify it under the * This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software * terms of the GNU Lesser General Public License as published by the Free Software
@ -14,19 +14,109 @@
*/ */
package org.oscim.generator; package org.oscim.generator;
import java.util.Comparator;
/** /**
* * based on ComparableTimSort:
* * everything below is Copyright OpenJDK, Oracle
*/ */
public class TileDistanceSort implements Comparator<JobTile> {
@Override public class TileDistanceSort {
public int compare(JobTile tile1, JobTile tile2) { public static void sort(JobTile[] a, int lo, int hi) {
if (tile1.distance == tile2.distance) int nRemaining = hi - lo;
if (nRemaining < 2) {
return;
}
int initRunLen = countRunAndMakeAscending(a, lo, hi);
binarySort(a, lo, hi, lo + initRunLen);
}
static int compareTo(JobTile a, JobTile b) {
if (a == null && b == null)
return 0; return 0;
return tile1.distance > tile2.distance ? 1 : -1; if (a == null)
return 1;
if (b == null)
return -1;
if (a.distance < b.distance) {
return -1;
}
if (a.distance > b.distance) {
return 1;
}
return 0;
}
private static void binarySort(JobTile[] a, int lo, int hi, int start)
{
assert ((lo <= start) && (start <= hi));
if (start == lo)
++start;
for (; start < hi; ++start)
{
JobTile pivot = a[start];
int left = lo;
int right = start;
assert (left <= right);
while (left < right) {
int mid = left + right >>> 1;
//if (pivot.compareTo(a[mid]) < 0)
if (compareTo(pivot, a[mid]) < 0)
right = mid;
else
left = mid + 1;
}
assert (left == right);
int n = start - left;
switch (n)
{
case 2:
a[(left + 2)] = a[(left + 1)];
//$FALL-THROUGH$
case 1:
a[(left + 1)] = a[left];
break;
default:
System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
}
private static int countRunAndMakeAscending(JobTile[] a, int lo, int hi)
{
assert (lo < hi);
int runHi = lo + 1;
if (runHi == hi) {
return 1;
}
if (compareTo((a[(runHi++)]), a[lo]) < 0) {
while ((runHi < hi) && (compareTo((a[runHi]), a[(runHi - 1)]) < 0))
++runHi;
reverseRange(a, lo, runHi);
} else {
while ((runHi < hi) && (compareTo((a[runHi]), a[(runHi - 1)]) >= 0)) {
++runHi;
}
}
return (runHi - lo);
}
private static void reverseRange(JobTile[] a, int lo, int hi)
{
--hi;
while (lo < hi) {
JobTile t = a[lo];
a[(lo++)] = a[hi];
a[(hi--)] = t;
}
} }
} }

View File

@ -26,6 +26,7 @@ import java.util.Arrays;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.generator.JobTile; import org.oscim.generator.JobTile;
import org.oscim.generator.TileDistanceSort;
import org.oscim.renderer.layer.TextItem; import org.oscim.renderer.layer.TextItem;
import org.oscim.renderer.layer.VertexPool; import org.oscim.renderer.layer.VertexPool;
import org.oscim.view.MapView; import org.oscim.view.MapView;
@ -471,10 +472,10 @@ public class TileManager {
t.vbo = null; t.vbo = null;
} }
mTilesCount--;
QuadTree.remove(t); QuadTree.remove(t);
t.state = STATE_NONE; t.state = STATE_NONE;
mTilesCount--;
} }
private static void updateTileDistances(Object[] tiles, int size, MapPosition mapPosition) { private static void updateTileDistances(Object[] tiles, int size, MapPosition mapPosition) {
@ -536,58 +537,38 @@ public class TileManager {
private static void limitCache(MapPosition mapPosition, int remove) { private static void limitCache(MapPosition mapPosition, int remove) {
MapTile[] tiles = mTiles; MapTile[] tiles = mTiles;
int size = mTilesSize;
// remove tiles that were never loaded // remove tiles that were never loaded
for (int i = 0, size = mTilesSize; i < size; i++) { for (int i = 0; i < size; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (t == null) if (t == null)
continue; continue;
// make sure tile cannot be used by GL or MapWorker Thread // make sure tile cannot be used by GL or MapWorker Thread
if (t.isLocked() || t.isActive()) { if ((t.state != 0) || t.isLocked()) {
continue; continue;
} }
clearTile(t); clearTile(t);
tiles[i] = null; tiles[i] = null;
remove--; remove--;
size--;
} }
if (remove > 5) { if (remove > 10) {
int size = mTilesSize; updateTileDistances(tiles, size, mapPosition);
if (size > mTilesCount) { // double start, end;
Log.d(TAG, "repack: " + size + " " + mTilesCount); // start = SystemClock.uptimeMillis();
int start = 0; TileDistanceSort.sort(tiles, 0, size);
// get first position to shift
while (start < size && tiles[start] != null)
start++;
int space = start + 1;
for (int end = 0; end < size;) {
// get the number of slots to shift
while (space < size && tiles[space] == null)
space++;
// get the position of next free slots
end = space;
while (end < size && tiles[end] != null)
end++;
// number of items to shift
int len = end - space;
if (len > 0) { //end = SystemClock.uptimeMillis();
System.arraycopy(tiles, space, tiles, start, len); //Log.d(TAG, "sort took " + (end - start) +
start = start + len; // "limitCache: repacked: " + mTilesSize + " to: " + mTilesCount);
space = end;
}
}
Log.d(TAG, "repacked tiles to: " + start);
Arrays.fill(mTiles, start, mTilesSize, null);
mTilesSize = size = start;
}
updateTileDistances(mTiles, size, mapPosition); // sorting also repacks the 'sparse' filled array
Arrays.sort(mTiles, 0, size); // so end of mTiles is at mTilesCount now
mTilesSize = size = mTilesCount;
for (int i = 1; i < remove; i++) { for (int i = 1; i < remove; i++) {
MapTile t = tiles[size - i]; MapTile t = tiles[size - i];