Implement size limit approach (Java routing)

This commit is contained in:
Victor Shcherb 2012-09-25 22:58:48 +02:00
parent a64904469f
commit 1aac6c9cb7
11 changed files with 183 additions and 87 deletions

View file

@ -123,7 +123,6 @@ public class RouterTestsSuite {
for (int i = 0; i < tests.getLength(); i++) {
Element e = (Element) tests.item(i);
BinaryRoutePlanner router = new BinaryRoutePlanner(lib, rs);
RoutingConfiguration.DEFAULT_DESIRABLE_TILES_IN_MEMORY = 100;
testRoute(e, router, config);
}
@ -159,7 +158,7 @@ public class RouterTestsSuite {
System.err.println("\n\n!! Skipped test case '" + testDescription + "' because 'best_percent' attribute is not specified \n\n" );
return;
}
RoutingContext ctx = new RoutingContext(config.build(vehicle));
RoutingContext ctx = new RoutingContext(config.build(vehicle, RoutingConfiguration.DEFAULT_MEMORY_LIMIT));
String skip = testCase.getAttribute("skip_comment");
if (skip != null && skip.length() > 0) {
System.err.println("\n\n!! Skipped test case '" + testDescription + "' because '" + skip + "'\n\n" );

View file

@ -49,7 +49,7 @@ public class BinaryInspector {
// test cases show info
//inspector(new String[]{"-vaddress",/* "-bbox=-121.785,37.35,-121.744,37.33", */"/home/victor/projects/OsmAnd/data/osm-gen/Map.obf"});
inspector(new String[]{/*"-vaddress", "-bbox=-121.785,37.35,-121.744,37.33", */"/home/victor/projects/OsmAnd/data/osm-gen/Netherlands_europe.obf"});
// test case extract parts
// test case
}

View file

@ -1,5 +1,6 @@
package net.osmand.binary;
import gnu.trove.map.hash.TIntObjectHashMap;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule;

View file

@ -42,13 +42,11 @@ public class BinaryRoutePlanner {
private static final int ROUTE_POINTS = 11;
private static final float TURN_DEGREE_MIN = 45;
private static final boolean SHOW_GC_SIZE = false;
public BinaryRoutePlanner(NativeLibrary nativeLib, BinaryMapIndexReader... map) {
this.nativeLib = nativeLib;
if(nativeLib != null) {
RoutingConfiguration.DEFAULT_DESIRABLE_TILES_IN_MEMORY = 100;
}
this.nativeLib = null; //nativeLib;
for (BinaryMapIndexReader mr : map) {
List<RouteRegion> rr = mr.getRoutingIndexes();
List<RouteSubregion> subregions = new ArrayList<BinaryMapRouteReaderAdapter.RouteSubregion>();
@ -378,9 +376,6 @@ public class BinaryRoutePlanner {
graphSegments = graphDirectSegments;
}
if(ctx.runTilesGC()) {
unloadUnusedTiles(ctx, ctx.config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY);
}
if(ctx.runRelaxingStrategy() ) {
relaxNotNeededSegments(ctx, graphDirectSegments, true);
relaxNotNeededSegments(ctx, graphReverseSegments, false);
@ -398,8 +393,9 @@ public class BinaryRoutePlanner {
return resultPrepared;
}
private void unloadUnusedTiles(RoutingContext ctx, int desirableSize) {
private void unloadUnusedTiles(RoutingContext ctx) {
// now delete all
float desirableSize = ctx.config.memoryLimitation * 0.7f;
List<RoutingTile> list = new ArrayList<RoutingContext.RoutingTile>();
TIntObjectIterator<RoutingTile> it = ctx.tiles.iterator();
int loaded = 0;
@ -428,16 +424,31 @@ public class BinaryRoutePlanner {
return v1 < v2 ? -1 : (v1 == v2 ? 0 : 1);
}
});
if (loaded >= 0.9f * desirableSize) {
int toUnload = Math.max(loaded / 5, loaded - desirableSize);
for (int i = 0; i < loaded; i++) {
list.get(i).access = 0;
if (i < toUnload) {
ctx.unloadTile(list.get(i), true);
while(ctx.getCurrentEstimatedSize() >= desirableSize && list.size() > loaded / 5) {
RoutingTile unload = list.remove(0);
// System.out.println("Unload " + unload);
unload.access = 0;
ctx.unloadTile(unload, true);
}
}
private static long runGCUsedMemory() {
Runtime runtime = Runtime.getRuntime();
long usedMem1 = runtime.totalMemory() - runtime.freeMemory();
long usedMem2 = Long.MAX_VALUE;
int cnt = 4;
while (cnt-- >= 0) {
for (int i = 0; (usedMem1 < usedMem2) && (i < 1000); ++i) {
runtime.runFinalization();
runtime.gc();
Thread.yield();
usedMem2 = usedMem1;
usedMem1 = runtime.totalMemory() - runtime.freeMemory();
}
}
return usedMem1;
}
private void relaxNotNeededSegments(RoutingContext ctx, PriorityQueue<RouteSegment> graphSegments, boolean inverse) {
@ -498,19 +509,23 @@ public class BinaryRoutePlanner {
System.out.println(logMsg);
}
private static void printInfo(String logMsg) {
log.warn(logMsg);
}
public void printDebugMemoryInformation(RoutingContext ctx, PriorityQueue<RouteSegment> graphDirectSegments, PriorityQueue<RouteSegment> graphReverseSegments,
TLongObjectHashMap<RouteSegment> visitedDirectSegments,TLongObjectHashMap<RouteSegment> visitedOppositeSegments) {
println("Time to calculate : " + (System.nanoTime() - ctx.timeToCalculate) / 1e6 + ", time to load : " + ctx.timeToLoad / 1e6);
println("Current loaded tiles : " + ctx.getCurrentlyLoadedTiles() + ", maximum loaded tiles " + ctx.maxLoadedTiles);
println("Loaded tiles " + ctx.loadedTiles + " (distinct "+ctx.distinctLoadedTiles+ "), unloaded tiles " + ctx.unloadedTiles +
printInfo("Time to calculate : " + (System.nanoTime() - ctx.timeToCalculate) / 1e6 + ", time to load : " + ctx.timeToLoad / 1e6);
printInfo("Current loaded tiles : " + ctx.getCurrentlyLoadedTiles() + ", maximum loaded tiles " + ctx.maxLoadedTiles);
printInfo("Loaded tiles " + ctx.loadedTiles + " (distinct "+ctx.distinctLoadedTiles+ "), unloaded tiles " + ctx.unloadedTiles +
" (distinct " + ctx.distinctUnloadedTiles.size()+") "+ ", loaded more than once same tiles "
+ ctx.loadedPrevUnloadedTiles );
println("Visited roads, " + ctx.visitedSegments + ", relaxed roads " + ctx.relaxedSegments);
printInfo("Visited roads, " + ctx.visitedSegments + ", relaxed roads " + ctx.relaxedSegments);
if (graphDirectSegments != null && graphReverseSegments != null) {
println("Priority queues sizes : " + graphDirectSegments.size() + "/" + graphReverseSegments.size());
printInfo("Priority queues sizes : " + graphDirectSegments.size() + "/" + graphReverseSegments.size());
}
if (visitedDirectSegments != null && visitedOppositeSegments != null) {
println("Visited segments sizes: " + visitedDirectSegments.size() + "/" + visitedOppositeSegments.size());
printInfo("Visited segments sizes: " + visitedDirectSegments.size() + "/" + visitedOppositeSegments.size());
}
}
@ -521,6 +536,24 @@ public class BinaryRoutePlanner {
tile.access++;
return tile;
}
if(ctx.getCurrentEstimatedSize() > 0.95 *ctx.config.memoryLimitation) {
int sz1 = ctx.getCurrentEstimatedSize();
long h1 = 0;
if(SHOW_GC_SIZE && sz1 > 0.7 * ctx.config.memoryLimitation ) {
runGCUsedMemory();
h1 = runGCUsedMemory();
}
int clt = ctx.getCurrentlyLoadedTiles();
unloadUnusedTiles(ctx);
if (h1 != 0 && ctx.getCurrentlyLoadedTiles() != clt) {
int sz2 = ctx.getCurrentEstimatedSize();
runGCUsedMemory();
long h2 = runGCUsedMemory();
float mb = (1 << 20);
log.warn("Unload tiles : estimated " + (sz1 - sz2) / mb + " ?= " + (h1 - h2) / mb+ " actual");
log.warn("Used after " + h2 / mb + " of " + Runtime.getRuntime().totalMemory() / mb + " max " + Runtime.getRuntime().maxMemory() / mb);
}
}
ctx.loadTileData(tile, null, nativeLib, map);
return tile;
}
@ -886,8 +919,8 @@ public class BinaryRoutePlanner {
// calculate time
for (int i = 0; i < result.size(); i++) {
if(ctx.runTilesGC()) {
unloadUnusedTiles(ctx, ctx.config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY);
if(ctx.getCurrentEstimatedSize() > 0.9 *ctx.config.memoryLimitation) {
unloadUnusedTiles(ctx);
}
RouteSegmentResult rr = result.get(i);
RouteDataObject road = rr.getObject();

View file

@ -20,11 +20,12 @@ public class RoutingConfiguration {
// Influence on A* : f(x) + heuristicCoefficient*g(X)
public double heuristicCoefficient = 1;
public static final int DEFAULT_MEMORY_LIMIT = 30;
// 1.1 tile load parameters (should not affect routing)
public int ZOOM_TO_LOAD_TILES = 13; // 12?, 14?
public int ITERATIONS_TO_RUN_GC = 100;
public static int DEFAULT_DESIRABLE_TILES_IN_MEMORY = 30;
public int NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = DEFAULT_DESIRABLE_TILES_IN_MEMORY;
public int memoryLimitation;
// 1.2 Dynamic road prioritizing (heuristic)
public boolean useDynamicRoadPrioritising = true;
@ -53,10 +54,10 @@ public class RoutingConfiguration {
private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>();
private Map<String, String> attributes = new LinkedHashMap<String, String>();
public RoutingConfiguration build(String router, String... specialization) {
return build(router, null, specialization);
public RoutingConfiguration build(String router, int memoryLimitMB, String... specialization) {
return build(router, null, memoryLimitMB, specialization);
}
public RoutingConfiguration build(String router, Double direction, String... specialization) {
public RoutingConfiguration build(String router, Double direction, int memoryLimitMB, String... specialization) {
if (!routers.containsKey(router)) {
router = defaultRouter;
}
@ -64,10 +65,15 @@ public class RoutingConfiguration {
i.initialDirection = direction;
i.heuristicCoefficient = parseSilentDouble(getAttribute(router, "heuristicCoefficient"), i.heuristicCoefficient);
i.ZOOM_TO_LOAD_TILES = parseSilentInt(getAttribute(router, "zoomToLoadTiles"), i.ZOOM_TO_LOAD_TILES);
i.ITERATIONS_TO_RUN_GC = parseSilentInt(getAttribute(router, "iterationsToRunGC"), i.ITERATIONS_TO_RUN_GC);
i.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = parseSilentInt(getAttribute(router, "desirableTilesInMemory"),
i.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY);
int desirable = parseSilentInt(getAttribute(router, "memoryLimitInMB"), 0);
if(desirable != 0) {
i.memoryLimitation = desirable * (1 << 20);
} else {
if(memoryLimitMB == 0) {
memoryLimitMB = DEFAULT_MEMORY_LIMIT;
}
i.memoryLimitation = memoryLimitMB * (1 << 20);
}
i.useDynamicRoadPrioritising = parseSilentBoolean(getAttribute(router, "useDynamicRoadPrioritising"), i.useDynamicRoadPrioritising);
i.useRelaxingStrategy = parseSilentBoolean(getAttribute(router, "useRelaxingStrategy"), i.useRelaxingStrategy);
i.dynamicRoadPriorityDistance = parseSilentInt(getAttribute(router, "dynamicRoadPriorityDistance"), i.dynamicRoadPriorityDistance);

View file

@ -1,5 +1,6 @@
package net.osmand.router;
import gnu.trove.iterator.TIntObjectIterator;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TLongObjectHashMap;
@ -31,7 +32,7 @@ public class RoutingContext {
public final RoutingConfiguration config;
// 1. Initial variables
private int garbageCollectorIteration = 0;
private int relaxingIteration = 0;
public long firstRoadId = 0;
public int firstRoadDirection = 0;
@ -70,6 +71,8 @@ public class RoutingContext {
// callback of processing segments
RouteSegmentVisitor visitor = null;
private TileStatistics global = new TileStatistics();
public RoutingContext(RoutingConfiguration config) {
this.config = config;
}
@ -90,15 +93,8 @@ public class RoutingContext {
return cnt;
}
public boolean runTilesGC() {
garbageCollectorIteration++;
int loadedTilesCritical = config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY * 3 /2;
if (garbageCollectorIteration > config.ITERATIONS_TO_RUN_GC ||
getCurrentlyLoadedTiles() > loadedTilesCritical) {
garbageCollectorIteration = 0;
return true;
}
return false;
public int getCurrentEstimatedSize(){
return global.size;
}
public boolean runRelaxingStrategy(){
@ -186,12 +182,64 @@ public class RoutingContext {
RoutingTile old = tiles.remove(l);
RoutingTile n = new RoutingTile(tile.tileX, tile.tileY, config.ZOOM_TO_LOAD_TILES);
n.isLoaded = old.isLoaded;
n.setUnloaded();
tiles.put(l, n);
unloadedTiles++;
global.size -= tile.tileStatistics.size;
distinctUnloadedTiles.add(l);
}
private static class TileStatistics {
public int size = 0;
public int allRoutes = 0;
public int coordinates = 0;
@Override
public String toString() {
return "All routes " + allRoutes +
" size " + (size / 1024f) + " KB coordinates " + coordinates + " ratio coord " + (((float)size) / coordinates)
+ " ratio routes " + (((float)size) / allRoutes);
}
public void addObject(RouteDataObject o) {
allRoutes++;
coordinates += o.getPointsLength() * 2;
// calculate size
int sz = 0;
sz += 8 + 4; // overhead
if (o.names != null) {
sz += 12;
TIntObjectIterator<String> it = o.names.iterator();
while(it.hasNext()) {
it.advance();
String vl = it.value();
sz += 12 + vl.length();
}
sz += 12 + o.names.size() * 25;
}
sz += 8; // id
// coordinates
sz += (8 + 4 + 4 * o.getPointsLength()) * 4;
sz += o.types == null ? 4 : (8 + 4 + 4 * o.types.length);
sz += o.restrictions == null ? 4 : (8 + 4 + 8 * o.restrictions.length);
sz += 4;
if (o.pointTypes != null) {
sz += 8 + 4 * o.pointTypes.length;
for (int i = 0; i < o.pointTypes.length; i++) {
sz += 4;
if (o.pointTypes[i] != null) {
sz += 8 + 8 * o.pointTypes[i].length;
}
}
}
// Standard overhead?
size += sz * 3;
// size += coordinates * 20;
}
}
public void loadTileData(final RoutingTile tile, final List<RouteDataObject> toFillIn, NativeLibrary nativeLib,
Map<BinaryMapIndexReader, List<RouteSubregion>> map) {
@ -200,15 +248,15 @@ public class RoutingContext {
final int zoomToLoad = 31 - tile.getZoom();
final int tileX = tile.getTileX();
final int tileY = tile.getTileY();
final TileStatistics ts = new TileStatistics();
ResultMatcher<RouteDataObject> matcher = new ResultMatcher<RouteDataObject>() {
int intersectionObjects = 0, all = 0, allout = 0;
@Override
public boolean publish(RouteDataObject o) {
if(o.getPointsLength() == 0) {
return false;
}
all++;
boolean out = false;
ts.allRoutes++;
int minx, maxx, miny, maxy;
minx = maxx = o.getPoint31XTile(0);
miny = maxy = o.getPoint31YTile(0);
@ -217,22 +265,15 @@ public class RoutingContext {
maxx = Math.max(o.getPoint31XTile(ti), maxx);
miny = Math.min(o.getPoint31YTile(ti), miny);
maxy = Math.max(o.getPoint31YTile(ti), maxy);
if(!tile.checkContains(o.getPoint31XTile(ti), o.getPoint31YTile(ti))) {
out = true;
}
}
minx = minx >> zoomToLoad;
maxx = maxx >> zoomToLoad;
miny = miny >> zoomToLoad;
maxy = maxy >> zoomToLoad;
if(minx > tileX || maxx < tileX || miny > tileY || maxy < tileY) {
allout++;
return false;
}
if(out) {
intersectionObjects++;
}
ts.addObject(o);
if (toFillIn != null) {
if (getRouter().acceptLine(o)) {
toFillIn.add(o);
@ -244,7 +285,7 @@ public class RoutingContext {
@Override
public String toString() {
return "Tile " + tileX + "/"+ tileY + " boundaries " + intersectionObjects + " of " + all + " out " + allout;
return "Tile " + tileX + "/"+ tileY + " : " + ts;
}
@Override
@ -290,12 +331,20 @@ public class RoutingContext {
}
}
}
loadedTiles++;
if (tile.isUnloaded()) {
loadedPrevUnloadedTiles++;
} else {
if(global != null) {
global.allRoutes += ts.allRoutes;
global.coordinates += ts.coordinates;
}
distinctLoadedTiles++;
}
tile.tileStatistics = ts;
global.size += ts.size;
// System.out.println("Loaded " + tile + " global " + global);
tile.setLoaded();
if(nativeRouteSearchResults.size() > 0) {
tile.nativeLib = nativeLib;
@ -405,6 +454,7 @@ public class RoutingContext {
private TLongObjectMap<RouteSegment> routes = new TLongObjectHashMap<RouteSegment>();
private TLongObjectHashMap<RouteDataObject> idObjects = new TLongObjectHashMap<RouteDataObject>();
private TileStatistics tileStatistics = new TileStatistics();
public RouteSegment getSegment(long id, RoutingContext ctx) {
if(nativeResults != null) {
@ -506,6 +556,11 @@ public class RoutingContext {
return tileX == (x31 >> (31 - zoom)) && tileY == (y31 >> (31 - zoom));
}
@Override
public String toString() {
return "Tile " + tileX + "/" + tileY + " : " + tileStatistics;
}
}
}

View file

@ -129,7 +129,6 @@
</avoid>
</routingProfile>
<routingProfile name="bicycle" baseProfile="bicycle" restrictionsAware="true" minDefaultSpeed="7" maxDefaultSpeed="16"
leftTurn="0" rightTurn="0" followSpeedLimitations="false" onewayAware="true">
<!-- <attribute name="relaxNodesIfStartDistSmallCoeff" value="2.5"/> -->

View file

@ -122,8 +122,7 @@ public class MapClusterLayer implements MapPanelLayer {
BinaryRoutePlanner router = new BinaryRoutePlanner(NativeSwingRendering.getDefaultFromSettings(),
rs.toArray(new BinaryMapIndexReader[rs.size()]));
Builder builder = RoutingConfiguration.getDefault();
RoutingConfiguration config = builder.build("car");
config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = 300;
RoutingConfiguration config = builder.build("car", RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 3);
RoutingContext ctx = new RoutingContext(config);
// find closest way
RouteSegment st = router.findRouteSegment(lat, lon, ctx);

View file

@ -305,20 +305,6 @@ public class MapRouterLayer implements MapPanelLayer {
}
// for vector rendering we should extract from osm
// 1. Ways (different kinds) with tag highway= ?,highway=stop ...
// 2. Junction = roundabout
// 3. barrier, traffic_calming=bump
// 4. Save {name, ref} of way to unify it
// + for future routing we should extract from osm
// 1. oneway
// 2. max_speed
// 3. toll
// 4. traffic_signals
// 5. max_heigtht, max_width, min_speed, ...
// 6. incline ?
public static List<Way> route_YOURS(LatLon start, LatLon end){
List<Way> res = new ArrayList<Way>();
long time = System.currentTimeMillis();
@ -626,7 +612,7 @@ public class MapRouterLayer implements MapPanelLayer {
String m = DataExtractionSettings.getSettings().getRouteMode();
String[] props = m.split("\\,");
BinaryRoutePlanner router = new BinaryRoutePlanner(NativeSwingRendering.getDefaultFromSettings(), rs);
RoutingConfiguration config = builder.build(props[0], props);
RoutingConfiguration config = builder.build(props[0], RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 3, props);
// config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = 300;
// config.ZOOM_TO_LOAD_TILES = 14;
RoutingContext ctx = new RoutingContext(config);
@ -638,13 +624,13 @@ public class MapRouterLayer implements MapPanelLayer {
if (st == null) {
throw new RuntimeException("Starting point for route not found");
}
System.out.println("ROAD TO START " + st.getRoad().getHighway() + " " + st.getRoad().id);
log.info("Start road " + st.getRoad().getHighway() + " " + st.getRoad().id);
RouteSegment e = router.findRouteSegment(end.getLatitude(), end.getLongitude(), ctx);
if (e == null) {
throw new RuntimeException("End point to calculate route was not found");
}
System.out.println("ROAD TO END " + e.getRoad().getHighway() + " " + e.getRoad().id);
log.info("End road " + e.getRoad().getHighway() + " " + e.getRoad().id);
List<RouteSegment> inters = new ArrayList<BinaryRoutePlanner.RouteSegment>();
if (intermediates != null) {

View file

@ -630,10 +630,14 @@ public class MapRenderRepositories {
handler.post(new Runnable() {
@Override
public void run() {
ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
AccessibleToast.makeText(context, context.getString(R.string.rendering_out_of_memory) + " (" + memoryInfo.availMem / 1048576L + " MB available) ", Toast.LENGTH_SHORT).show();
// ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
// ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
// activityManager.getMemoryInfo(memoryInfo);
// int avl = (int) (memoryInfo.availMem / (1 << 20));
int max = (int) (Runtime.getRuntime().maxMemory() / (1 << 20));
int avl = (int) (Runtime.getRuntime().freeMemory() / (1 << 20));
String s = " (" + avl + " MB available of " + max + ") ";
AccessibleToast.makeText(context, context.getString(R.string.rendering_out_of_memory) + s , Toast.LENGTH_SHORT).show();
}
});
} finally {

View file

@ -27,6 +27,7 @@ import net.osmand.GPXUtilities.Track;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.LogUtil;
import net.osmand.access.AccessibleToast;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.osm.LatLon;
import net.osmand.plus.OsmandApplication;
@ -55,6 +56,7 @@ import org.xml.sax.SAXException;
import android.app.ActivityManager;
import android.content.Context;
import android.location.Location;
import android.widget.Toast;
public class RouteProvider {
private static final org.apache.commons.logging.Log log = LogUtil.getLog(RouteProvider.class);
@ -350,7 +352,15 @@ public class RouteProvider {
specs.add(GeneralRouter.AVOID_UNPAVED);
}
String[] specialization = specs.toArray(new String[specs.size()]);
RoutingContext ctx = new RoutingContext(config.build(p.name().toLowerCase(), start.hasBearing() ? start.getBearing() / 180d * Math.PI : null, specialization));
float mb = (1 << 20);
Runtime rt = Runtime.getRuntime();
// make visible
int memoryLimit = (int) (0.9 * ((rt.maxMemory() - rt.totalMemory()) + rt.freeMemory()) / mb);
log.error("Use " + memoryLimit + "Free " + rt.freeMemory() / mb + " of " + rt.totalMemory() / mb + " max " + rt.maxMemory() / mb);
RoutingConfiguration cf = config.build(p.name().toLowerCase(), start.hasBearing() ? start.getBearing() / 180d * Math.PI : null,
memoryLimit, specialization);
RoutingContext ctx = new RoutingContext(cf);
ctx.interruptable = interruptable;
ctx.previouslyCalculatedRoute = previousRoute;
RouteSegment st= router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx);
@ -387,10 +397,14 @@ public class RouteProvider {
return new RouteCalculationResult(result, start, end, intermediates, app, leftSide);
}
} catch (OutOfMemoryError e) {
ActivityManager activityManager = (ActivityManager)app.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return new RouteCalculationResult("Not enough process memory "+ "(" + memoryInfo.availMem / 1048576L + " MB available) ");
// ActivityManager activityManager = (ActivityManager)app.getSystemService(Context.ACTIVITY_SERVICE);
// ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
// activityManager.getMemoryInfo(memoryInfo);
// int avl = (int) (memoryInfo.availMem / (1 << 20));
int max = (int) (Runtime.getRuntime().maxMemory() / (1 << 20));
int avl = (int) (Runtime.getRuntime().freeMemory() / (1 << 20));
String s = " (" + avl + " MB available of " + max + ") ";
return new RouteCalculationResult("Not enough process memory "+ s);
}
}