Try different approach loading tiles
This commit is contained in:
parent
44218fbe0a
commit
f8673d5d98
7 changed files with 75 additions and 79 deletions
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue