Try different approach loading tiles

This commit is contained in:
Victor Shcherb 2012-09-28 09:31:36 +02:00
parent 44218fbe0a
commit f8673d5d98
7 changed files with 75 additions and 79 deletions

View file

@ -51,27 +51,27 @@ public class JUnitRouteTest {
}
@Test
public void runCZ() throws SAXException, IOException, ParserConfigurationException {
public void runCZ() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("cz.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runNL() throws SAXException, IOException, ParserConfigurationException {
public void runNL() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("nl.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runNL2() throws SAXException, IOException, ParserConfigurationException {
public void runNL2() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("nl2.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runNLLeid() throws SAXException, IOException, ParserConfigurationException {
public void runNLLeid() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("nl_leid.test.xml"), rs, RoutingConfiguration.getDefault());
}
@Test
public void runBLR() throws SAXException, IOException, ParserConfigurationException {
public void runBLR() throws Exception {
RouterTestsSuite.test(lib, getClass().getResourceAsStream("blr.test.xml"), rs, RoutingConfiguration.getDefault());
}

View file

@ -9,7 +9,6 @@ import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.osmand.NativeLibrary;
import net.osmand.binary.BinaryMapIndexReader;
@ -78,7 +77,7 @@ public class RouterTestsSuite {
}
}
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
public static void main(String[] args) throws Exception {
Parameters params = Parameters.init(args);
if(params.tests.isEmpty() || params.obfDir == null) {
println("Run router tests is console utility to test route calculation for osmand.");
@ -117,7 +116,7 @@ public class RouterTestsSuite {
}
public static boolean test(NativeLibrary lib, InputStream resource, BinaryMapIndexReader[] rs, RoutingConfiguration.Builder config) throws SAXException, IOException, ParserConfigurationException {
public static boolean test(NativeLibrary lib, InputStream resource, BinaryMapIndexReader[] rs, RoutingConfiguration.Builder config) throws Exception {
Document testSuite = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(resource));
NodeList tests = testSuite.getElementsByTagName("test");
@ -147,7 +146,7 @@ public class RouterTestsSuite {
return false;
}
private static void testRoute(Element testCase, Builder config, NativeLibrary lib, BinaryMapIndexReader[] rs) throws IOException, SAXException {
private static void testRoute(Element testCase, Builder config, NativeLibrary lib, BinaryMapIndexReader[] rs) throws IOException, SAXException, InterruptedException {
String vehicle = testCase.getAttribute("vehicle");
int loadedTiles = (int) parseFloat(testCase, "loadedTiles");
int visitedSegments = (int) parseFloat(testCase, "visitedSegments");

View file

@ -122,7 +122,7 @@ public class BinaryRoutePlanner {
return road;
}
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, List<RouteSegment> intermediate, boolean leftSideNavigation) throws IOException {
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, List<RouteSegment> intermediate, boolean leftSideNavigation) throws IOException, InterruptedException {
if(intermediate != null && intermediate.size() > 0) {
ArrayList<RouteSegment> ps = new ArrayList<RouteSegment>(intermediate);
ArrayList<RouteSegmentResult> firstPartRecalculatedRoute = null;
@ -149,7 +149,8 @@ public class BinaryRoutePlanner {
local.previouslyCalculatedRoute = firstPartRecalculatedRoute;
}
local.visitor = ctx.visitor;
List<RouteSegmentResult> res = searchRouteInternal(local, ps.get(i), ps.get(i + 1), leftSideNavigation);
List<RouteSegmentResult> res = searchRouteInternalPrepare(local, ps.get(i), ps.get(i + 1), leftSideNavigation);
results.addAll(res);
ctx.distinctLoadedTiles += local.distinctLoadedTiles;
ctx.loadedTiles += local.loadedTiles;
@ -173,21 +174,38 @@ public class BinaryRoutePlanner {
return searchRoute(ctx, start, end, leftSideNavigation);
}
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException {
List<RouteSegmentResult> result = searchRouteInternal(ctx, start, end, leftSideNavigation);
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
List<RouteSegmentResult> result = searchRouteInternalPrepare(ctx, start, end, leftSideNavigation);
if(result != null) {
printResults(ctx, start, end, result);
}
ctx.unloadAllData();
if (RoutingContext.SHOW_GC_SIZE) {
int sz = ctx.global.size;
System.out.println("Subregion size " + ctx.subregionTiles.size() + " " + " tiles " + ctx.tiles.size());
ctx.runGCUsedMemory();
long h1 = ctx.runGCUsedMemory();
ctx.unloadAllData();
ctx.runGCUsedMemory();
long h2 = ctx.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Unload context : estimated " + sz / mb + " ?= " + (h1 - h2) / mb + " actual");
}
return result;
}
private List<RouteSegmentResult> searchRouteInternalPrepare(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
// Split into 2 methods to let GC work in between
searchRouteInternal(ctx, start, end, leftSideNavigation);
// 4. Route is found : collect all segments and prepare result
return prepareResult(ctx, start, end, leftSideNavigation);
}
/**
* Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm)
* return list of segments
*/
public List<RouteSegmentResult> searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException {
private void searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
// measure time
ctx.timeToLoad = 0;
ctx.visitedSegments = 0;
@ -323,15 +341,11 @@ public class BinaryRoutePlanner {
}
// check if interrupted
if(ctx.interruptable != null && ctx.interruptable.isCancelled()) {
return new ArrayList<RouteSegmentResult>();
throw new InterruptedException("Route calculation interrupted");
}
}
println("Result is found");
printDebugMemoryInformation(ctx, graphDirectSegments, graphReverseSegments, visitedDirectSegments, visitedOppositeSegments);
// 4. Route is found : collect all segments and prepare result
List<RouteSegmentResult> resultPrepared = prepareResult(ctx, start, end, leftSideNavigation);
return resultPrepared;
}

View file

@ -52,6 +52,7 @@ public class RoutingContext {
// 2. Routing memory cache (big objects)
TIntObjectHashMap<RoutingTile> tiles = new TIntObjectHashMap<RoutingContext.RoutingTile>();
// Map<Integer, RoutingTile> tiles = new LinkedHashMap<Integer, RoutingContext.RoutingTile>();
// need to be array list
List<RoutingSubregionTile> subregionTiles = new ArrayList<RoutingSubregionTile>();
@ -59,7 +60,6 @@ public class RoutingContext {
TLongSet nonRestrictedIds = new TLongHashSet();
ArrayList<RouteSegment> segmentsToVisitPrescripted = new ArrayList<BinaryRoutePlanner.RouteSegment>(5);
ArrayList<RouteSegment> segmentsToVisitNotForbidden = new ArrayList<BinaryRoutePlanner.RouteSegment>(5);
TLongObjectHashMap<RouteDataObject> excludeDuplications = new TLongObjectHashMap<RouteDataObject>();
// 4. Final results
@ -84,8 +84,8 @@ public class RoutingContext {
// callback of processing segments
RouteSegmentVisitor visitor = null;
private TileStatistics global = new TileStatistics();
private static final boolean SHOW_GC_SIZE = false;
public TileStatistics global = new TileStatistics();
public static final boolean SHOW_GC_SIZE = false;
@ -226,23 +226,17 @@ public class RoutingContext {
}
public void unloadAllData(RoutingContext except) {
// List<RoutingTile> toUnload = new ArrayList<RoutingContext.RoutingTile>();
// for(RoutingTile t : local.tiles.valueCollection()){
// if(!ctx.tiles.contains(t.getId())) {
// toUnload.add(t);
// }
// }
// for(RoutingTile tl : toUnload) {
// local.unloadTile(tl, false);
// }
for (RoutingSubregionTile tl : subregionTiles) {
if (tl.isLoaded()) {
if(except == null || except.searchSubregionTile(tl.subregion) < 0){
tl.unload();
unloadedTiles ++;
global.size -= tl.tileStatistics.size;
}
}
}
subregionTiles.clear();
tiles.clear();
}
private int searchSubregionTile(RouteSubregion subregion){
@ -279,6 +273,7 @@ public class RoutingContext {
private void loadSubregionTile(final RoutingSubregionTile ts) {
boolean wasUnloaded = ts.isUnloaded();
int ucount = ts.getUnloadCont();
if (nativeLib == null) {
long now = System.nanoTime();
try {
@ -323,7 +318,9 @@ public class RoutingContext {
}
loadedTiles++;
if (wasUnloaded) {
loadedPrevUnloadedTiles++;
if(ucount == 1) {
loadedPrevUnloadedTiles++;
}
} else {
if(global != null) {
global.allRoutes += ts.tileStatistics.allRoutes;
@ -348,19 +345,16 @@ public class RoutingContext {
long now = System.nanoTime();
// int rg = r.getValue().get(0).routeReg.regionsRead;
List<RouteSubregion> subregs = r.getKey().searchRouteIndexTree(request, r.getValue());
for(RouteSubregion sr : subregs) {
List<RoutingTile> tiles = getRoutingTiles(sr.left, sr.top, sr.right, sr.bottom);
for (RouteSubregion sr : subregs) {
int ind = searchSubregionTile(sr);
RoutingSubregionTile found;
if(ind < 0){
if (ind < 0) {
found = new RoutingSubregionTile(sr);
subregionTiles.add(-(ind+1), found);
subregionTiles.add(-(ind + 1), found);
} else {
found = subregionTiles.get(ind);
}
for(RoutingTile t : tiles) {
t.searchSubregionAndAdd(sr, found);
}
tile.searchSubregionAndAdd(sr, found);
}
timeToLoadHeaders += (System.nanoTime() - now);
}
@ -396,10 +390,11 @@ public class RoutingContext {
RoutingTile tl = it.next();
tl.getAllObjects(toFillIn, this);
}
timeToLoadHeaders += (System.nanoTime() - now);
timeToFindInitialSegments += (System.nanoTime() - now);
}
private RoutingTile getRoutingTile(int x31, int y31, boolean load){
// long now = System.nanoTime();
int xloc = x31 >> (31 - config.ZOOM_TO_LOAD_TILES);
int yloc = y31 >> (31 - config.ZOOM_TO_LOAD_TILES);
int l = (xloc << config.ZOOM_TO_LOAD_TILES) + yloc;
@ -443,28 +438,10 @@ public class RoutingContext {
}
}
}
// timeToLoad += (System.nanoTime() - now);
return tile;
}
private List<RoutingTile> getRoutingTiles(int leftX, int topY, int rightX, int bottomY) {
int xl = leftX >> (31 - config.ZOOM_TO_LOAD_TILES);
int yt = topY >> (31 - config.ZOOM_TO_LOAD_TILES);
int xr = rightX >> (31 - config.ZOOM_TO_LOAD_TILES);
int yb = bottomY >> (31 - config.ZOOM_TO_LOAD_TILES);
List<RoutingTile> res = new ArrayList<RoutingContext.RoutingTile>();
for (int xloc = xl; xloc <= xr; xloc++) {
for (int yloc = yt; yloc <= yb; yloc++) {
int l = (xloc << config.ZOOM_TO_LOAD_TILES) + yloc;
RoutingTile tl = tiles.get(l);
if (tl == null) {
tl = new RoutingTile(xloc, yloc, config.ZOOM_TO_LOAD_TILES);
tiles.put(l, tl);
}
res.add(tiles.get(l));
}
}
return res;
}
public boolean checkIfMemoryLimitCritical() {
return getCurrentEstimatedSize() > 0.9 * config.memoryLimitation;
@ -502,6 +479,8 @@ public class RoutingContext {
i++;
// System.out.println("Unload " + unload);
unload.unload();
unloadedTiles ++;
global.size -= unload.tileStatistics.size;
// tile could be cleaned from routing tiles and deleted from whole list
// List<RoutingTile> ts = getRoutingTiles(tile.subregion.left, tile.subregion.top, tile.subregion.right, tile.subregion.bottom);
@ -511,7 +490,7 @@ public class RoutingContext {
}
}
private static long runGCUsedMemory() {
protected static long runGCUsedMemory() {
Runtime runtime = Runtime.getRuntime();
long usedMem1 = runtime.totalMemory() - runtime.freeMemory();
long usedMem2 = Long.MAX_VALUE;
@ -559,15 +538,15 @@ public class RoutingContext {
this.subregion = subregion;
}
private void loadAllObjects(final List<RouteDataObject> toFillIn, RoutingContext ctx) {
private void loadAllObjects(final List<RouteDataObject> toFillIn, RoutingContext ctx, TLongObjectHashMap<RouteDataObject> excludeDuplications) {
if(routes != null) {
Iterator<RouteSegment> it = routes.valueCollection().iterator();
while(it.hasNext()){
RouteSegment rs = it.next();
while(rs != null){
RouteDataObject ro = rs.road;
if (!ctx.excludeDuplications.contains(ro.id)) {
ctx.excludeDuplications.put(ro.id, ro);
if (!excludeDuplications.contains(ro.id)) {
excludeDuplications.put(ro.id, ro);
toFillIn.add(ro);
}
rs = rs.next;
@ -677,7 +656,7 @@ public class RoutingContext {
public void load(NativeRouteSearchResult r) {
isLoaded = Math.abs(isLoaded) + 1;
searchResult = r;
// FIXME
throw new UnsupportedOperationException("tileStatistics = new TileStatistics()");
// tileStatistics = new TileStatistics();
}
}
@ -730,28 +709,28 @@ public class RoutingContext {
}
public void getAllObjects(final List<RouteDataObject> toFillIn, RoutingContext ctx) {
ctx.excludeDuplications.clear();
TLongObjectHashMap<RouteDataObject> excludeDuplications = new TLongObjectHashMap<RouteDataObject>();
if (routes != null) {
for (RouteDataObject ro : routes) {
if (!ctx.excludeDuplications.contains(ro.id)) {
ctx.excludeDuplications.put(ro.id, ro);
if (!excludeDuplications.contains(ro.id)) {
excludeDuplications.put(ro.id, ro);
toFillIn.add(ro);
}
}
}
for (RoutingSubregionTile rs : subregions) {
rs.loadAllObjects(toFillIn, ctx);
rs.loadAllObjects(toFillIn, ctx, excludeDuplications);
}
}
public RouteSegment getSegment(int x31, int y31, RoutingContext ctx) {
ctx.excludeDuplications.clear();
TLongObjectHashMap<RouteDataObject> excludeDuplications = new TLongObjectHashMap<RouteDataObject>();
RouteSegment original = null;
if (routes != null) {
for (RouteDataObject ro : routes) {
for (int i = 0; i < ro.pointsX.length; i++) {
if (ro.getPoint31XTile(i) == x31 && ro.getPoint31YTile(i) == y31) {
ctx.excludeDuplications.put(ro.id, ro);
excludeDuplications.put(ro.id, ro);
RouteSegment segment = new RouteSegment(ro, i);
segment.next = original;
original = segment;
@ -759,9 +738,9 @@ public class RoutingContext {
}
}
}
for (RoutingSubregionTile rs : subregions) {
original = rs.loadRouteSegment(x31, y31, ctx, ctx.excludeDuplications, original);
}
for (RoutingSubregionTile rs : subregions) {
original = rs.loadRouteSegment(x31, y31, ctx, excludeDuplications, original);
}
return original;
}
@ -798,7 +777,7 @@ public class RoutingContext {
}
}
private static class TileStatistics {
protected static class TileStatistics {
public int size = 0;
public int allRoutes = 0;
public int coordinates = 0;
@ -842,7 +821,7 @@ public class RoutingContext {
}
}
// Standard overhead?
size += sz * 3;
size += sz * 3.5;
// size += coordinates * 20;
}
}

View file

@ -9,7 +9,7 @@
<!-- OPTIMAL -->
<attribute name="zoomToLoadTiles" value="16" />
<!-- by default it is 15 -->
<attribute name="memoryLimitInMB" value="90" />
<attribute name="memoryLimitInMB" value="50" />
<!-- 1.2 Dynamic road prioritizing (heuristic) -->
<attribute name="useDynamicRoadPrioritising" value="true" />

View file

@ -611,7 +611,7 @@ public class MapRouterLayer implements MapPanelLayer {
String m = DataExtractionSettings.getSettings().getRouteMode();
String[] props = m.split("\\,");
BinaryRoutePlanner router = new BinaryRoutePlanner();
RoutingConfiguration config = builder.build(props[0], RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 2, props);
RoutingConfiguration config = builder.build(props[0], RoutingConfiguration.DEFAULT_MEMORY_LIMIT / 2, props);
// config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = 300;
// config.ZOOM_TO_LOAD_TILES = 14;
RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(), rs);
@ -748,6 +748,8 @@ public class MapRouterLayer implements MapPanelLayer {
}
} catch (IOException e) {
ExceptionHandler.handle(e);
} catch (InterruptedException e) {
ExceptionHandler.handle(e);
} finally {
playPauseButton.setVisible(false);
nextTurn.setVisible(false);

View file

@ -396,6 +396,8 @@ public class RouteProvider {
} else {
return new RouteCalculationResult(result, start, end, intermediates, app, leftSide);
}
} catch (InterruptedException e) {
return new RouteCalculationResult("Route calculation was interrupted");
} catch (OutOfMemoryError e) {
// ActivityManager activityManager = (ActivityManager)app.getSystemService(Context.ACTIVITY_SERVICE);
// ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();