performance patches
This commit is contained in:
parent
176beba6f6
commit
46db0104e5
13 changed files with 469 additions and 280 deletions
|
|
@ -1,172 +0,0 @@
|
|||
/**
|
||||
* Implementation for the open-set
|
||||
* that should be somewhat faster
|
||||
* and memory-efficient than the original
|
||||
* version based on java.util.TreeSet
|
||||
*
|
||||
* It relies on the two double-linked
|
||||
* lists implemented in OsmPath
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.router;
|
||||
|
||||
import btools.mapaccess.OsmNode;
|
||||
|
||||
public class OpenSet
|
||||
{
|
||||
private OsmPath start = new OsmPath();
|
||||
private OsmPath index2 = new OsmPath();
|
||||
|
||||
private int addCount = 0;
|
||||
|
||||
private int size = 0;
|
||||
|
||||
public void clear()
|
||||
{
|
||||
start.nextInSet = null;
|
||||
start.nextInIndexSet = null;
|
||||
index2.nextInIndexSet = null;
|
||||
size = 0;
|
||||
addCount = 0;
|
||||
}
|
||||
|
||||
public void add( OsmPath path )
|
||||
{
|
||||
int ac = path.adjustedCost;
|
||||
OsmPath p1 = index2;
|
||||
|
||||
// fast forward along index2
|
||||
while( p1.nextInIndexSet != null && p1.nextInIndexSet.adjustedCost < ac )
|
||||
{
|
||||
p1 = p1.nextInIndexSet;
|
||||
}
|
||||
if ( p1 == index2 )
|
||||
{
|
||||
p1 = start;
|
||||
}
|
||||
|
||||
// search using index1
|
||||
for(;;)
|
||||
{
|
||||
if ( p1.nextInIndexSet != null && p1.nextInIndexSet.adjustedCost < ac )
|
||||
{
|
||||
p1 = p1.nextInIndexSet;
|
||||
}
|
||||
else if ( p1.nextInSet != null && p1.nextInSet.adjustedCost < ac )
|
||||
{
|
||||
p1 = p1.nextInSet;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
OsmPath p2 = p1.nextInSet;
|
||||
|
||||
p1.nextInSet = path;
|
||||
path.prevInSet = p1;
|
||||
path.nextInSet = p2;
|
||||
if ( p2 != null ) { p2.prevInSet = path; }
|
||||
size++;
|
||||
|
||||
addCount++;
|
||||
|
||||
// feed random samples to the indices
|
||||
if ( (addCount & 31) == 0 )
|
||||
{
|
||||
addIndex( path, start );
|
||||
}
|
||||
else if ( (addCount & 1023) == 1023 )
|
||||
{
|
||||
addIndex( path, index2 );
|
||||
}
|
||||
}
|
||||
|
||||
public void remove( OsmPath path )
|
||||
{
|
||||
OsmPath p1 = path.prevInSet;
|
||||
OsmPath p2 = path.nextInSet;
|
||||
if ( p1 == null )
|
||||
{
|
||||
return; // not in set
|
||||
}
|
||||
path.prevInSet = null;
|
||||
path.nextInSet = null;
|
||||
if ( p2 != null )
|
||||
{
|
||||
p2.prevInSet = p1;
|
||||
}
|
||||
p1.nextInSet = p2;
|
||||
|
||||
removeIndex( path );
|
||||
|
||||
size--;
|
||||
}
|
||||
|
||||
public OsmPath first()
|
||||
{
|
||||
return start.nextInSet;
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public int[] getExtract()
|
||||
{
|
||||
int div = size / 1000 + 1;
|
||||
|
||||
int[] res = new int[size/div * 2];
|
||||
int i = 0;
|
||||
int cnt = 0;
|
||||
for( OsmPath p = start.nextInSet; p != null; p = p.nextInSet )
|
||||
{
|
||||
if ( (++cnt) % div == 0 )
|
||||
{
|
||||
OsmNode n = p.getLink().targetNode;
|
||||
res[i++] = n.ilon;
|
||||
res[i++] = n.ilat;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// index operations
|
||||
|
||||
private void addIndex( OsmPath path, OsmPath index )
|
||||
{
|
||||
int ac = path.adjustedCost;
|
||||
OsmPath p1 = index;
|
||||
OsmPath p2 = p1.nextInIndexSet;
|
||||
while( p2 != null && p2.adjustedCost < ac )
|
||||
{
|
||||
p1 = p2;
|
||||
p2 = p2.nextInIndexSet;
|
||||
}
|
||||
p1.nextInIndexSet = path;
|
||||
path.prevInIndexSet = p1;
|
||||
path.nextInIndexSet = p2;
|
||||
if ( p2 != null ) { p2.prevInIndexSet = path; }
|
||||
}
|
||||
|
||||
|
||||
private void removeIndex( OsmPath path )
|
||||
{
|
||||
OsmPath p1 = path.prevInIndexSet;
|
||||
OsmPath p2 = path.nextInIndexSet;
|
||||
if ( p1 == null )
|
||||
{
|
||||
return; // not in set
|
||||
}
|
||||
path.prevInIndexSet = null;
|
||||
path.nextInIndexSet = null;
|
||||
if ( p2 != null )
|
||||
{
|
||||
p2.prevInIndexSet = p1;
|
||||
}
|
||||
p1.nextInIndexSet = p2;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,12 +9,6 @@ import btools.mapaccess.*;
|
|||
|
||||
final class OsmPath implements OsmLinkHolder
|
||||
{
|
||||
// double-linked lists for the openSet
|
||||
public OsmPath nextInSet;
|
||||
public OsmPath prevInSet;
|
||||
public OsmPath nextInIndexSet;
|
||||
public OsmPath prevInIndexSet;
|
||||
|
||||
/**
|
||||
* The cost of that path (a modified distance)
|
||||
*/
|
||||
|
|
@ -30,12 +24,7 @@ final class OsmPath implements OsmLinkHolder
|
|||
// if the corresponding node has not
|
||||
public short selev;
|
||||
|
||||
public int adjustedCost = 0;
|
||||
|
||||
public void setAirDistanceCostAdjustment( int costAdjustment )
|
||||
{
|
||||
adjustedCost = cost + costAdjustment;
|
||||
}
|
||||
public int airdistance = 0; // distance to endpos
|
||||
|
||||
private OsmNode sourcenode;
|
||||
private OsmLink link;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.FileWriter;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import btools.mapaccess.OsmPos;
|
||||
import btools.util.CompactLongMap;
|
||||
|
|
@ -219,7 +220,7 @@ public final class OsmTrack
|
|||
sb.append( " xmlns=\"http://www.topografix.com/GPX/1/1\" \n" );
|
||||
sb.append( " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" );
|
||||
sb.append( " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n" );
|
||||
sb.append( " creator=\"BRouter-1.0.4\" version=\"1.1\">\n" );
|
||||
sb.append( " creator=\"BRouter-1.1\" version=\"1.1\">\n" );
|
||||
sb.append( " <trk>\n" );
|
||||
sb.append(" <name>").append(name).append("</name>\n");
|
||||
sb.append( " <trkseg>\n" );
|
||||
|
|
@ -286,6 +287,8 @@ public final class OsmTrack
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<String> iternity;
|
||||
|
||||
public String formatAsGeoJson()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(8192);
|
||||
|
|
@ -296,13 +299,24 @@ public final class OsmTrack
|
|||
sb.append( " {\n" );
|
||||
sb.append( " \"type\": \"Feature\",\n" );
|
||||
sb.append( " \"properties\": {\n" );
|
||||
sb.append( " \"creator\": \"BRouter-1.0.4\",\n" );
|
||||
sb.append( " \"creator\": \"BRouter-1.1\",\n" );
|
||||
sb.append( " \"name\": \"" ).append( name ).append( "\",\n" );
|
||||
sb.append( " \"track-length\": \"" ).append( distance ).append( "\",\n" );
|
||||
sb.append( " \"filtered ascend\": \"" ).append( ascend ).append( "\",\n" );
|
||||
sb.append( " \"plain-ascend\": \"" ).append( plainAscend ).append( "\",\n" );
|
||||
sb.append( " \"cost\": \"" ).append( cost ).append( "\"\n" );
|
||||
sb.append( " },\n" );
|
||||
|
||||
if ( iternity != null )
|
||||
{
|
||||
sb.append( " \"iternity\": [\n" );
|
||||
for( String s : iternity )
|
||||
{
|
||||
sb.append( " \"").append( s ).append( "\",\n" );
|
||||
}
|
||||
sb.deleteCharAt( sb.lastIndexOf( "," ) );
|
||||
sb.append( " ],\n" );
|
||||
}
|
||||
sb.append( " \"geometry\": {\n" );
|
||||
sb.append( " \"type\": \"LineString\",\n" );
|
||||
sb.append( " \"coordinates\": [\n" );
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ public final class RoutingContext implements DistanceChecker
|
|||
public BExpressionContext expctxWay;
|
||||
public BExpressionContext expctxNode;
|
||||
|
||||
public boolean serversizing = false;
|
||||
|
||||
public int downhillcostdiv;
|
||||
public int downhillcutoff;
|
||||
public int uphillcostdiv;
|
||||
|
|
@ -51,6 +53,12 @@ public final class RoutingContext implements DistanceChecker
|
|||
public int elevationpenaltybuffer;
|
||||
public int elevationmaxbuffer;
|
||||
public int elevationbufferreduce;
|
||||
|
||||
public double cost1speed;
|
||||
public double additionalcostfactor;
|
||||
public double changetime;
|
||||
public double buffertime;
|
||||
public double waittimeadjustment;
|
||||
|
||||
public void readGlobalConfig( BExpressionContext expctxGlobal )
|
||||
{
|
||||
|
|
@ -67,6 +75,12 @@ public final class RoutingContext implements DistanceChecker
|
|||
elevationpenaltybuffer = (int)(expctxGlobal.getVariableValue( "elevationpenaltybuffer", 5.f )*1000000);
|
||||
elevationmaxbuffer = (int)(expctxGlobal.getVariableValue( "elevationmaxbuffer", 10.f )*1000000);
|
||||
elevationbufferreduce = (int)(expctxGlobal.getVariableValue( "elevationbufferreduce", 0.f )*10000);
|
||||
|
||||
cost1speed = expctxGlobal.getVariableValue( "cost1speed", 22.f );
|
||||
additionalcostfactor = expctxGlobal.getVariableValue( "additionalcostfactor", 1.5f );
|
||||
changetime = expctxGlobal.getVariableValue( "changetime", 180.f );
|
||||
buffertime = expctxGlobal.getVariableValue( "buffertime", 120.f );
|
||||
waittimeadjustment = expctxGlobal.getVariableValue( "waittimeadjustment", 0.9f );
|
||||
}
|
||||
|
||||
public RoutingMessageHandler messageHandler = new RoutingMessageHandler();
|
||||
|
|
|
|||
|
|
@ -15,32 +15,33 @@ import btools.mapaccess.OsmLink;
|
|||
import btools.mapaccess.OsmLinkHolder;
|
||||
import btools.mapaccess.OsmNode;
|
||||
import btools.mapaccess.OsmNodesMap;
|
||||
import btools.util.SortedHeap;
|
||||
|
||||
public class RoutingEngine extends Thread
|
||||
{
|
||||
private OsmNodesMap nodesMap;
|
||||
private NodesCache nodesCache;
|
||||
private OpenSet openSet = new OpenSet();
|
||||
private SortedHeap<OsmPath> openSet = new SortedHeap<OsmPath>();
|
||||
private boolean finished = false;
|
||||
|
||||
private List<OsmNodeNamed> waypoints = null;
|
||||
protected List<OsmNodeNamed> waypoints = null;
|
||||
private int linksProcessed = 0;
|
||||
|
||||
private OsmTrack foundTrack = new OsmTrack();
|
||||
protected OsmTrack foundTrack = new OsmTrack();
|
||||
private OsmTrack foundRawTrack = null;
|
||||
private int alternativeIndex = 0;
|
||||
|
||||
private String errorMessage = null;
|
||||
protected String errorMessage = null;
|
||||
|
||||
private volatile boolean terminated;
|
||||
|
||||
private File profileDir;
|
||||
private String segmentDir;
|
||||
protected File profileDir;
|
||||
protected String segmentDir;
|
||||
private String outfileBase;
|
||||
private String logfileBase;
|
||||
private boolean infoLogEnabled;
|
||||
private Writer infoLogWriter;
|
||||
private RoutingContext routingContext;
|
||||
protected RoutingContext routingContext;
|
||||
|
||||
private double airDistanceCostFactor;
|
||||
private OsmTrack guideTrack;
|
||||
|
|
@ -80,8 +81,8 @@ public class RoutingEngine extends Thread
|
|||
BExpressionMetaData meta = new BExpressionMetaData();
|
||||
|
||||
BExpressionContext expctxGlobal = new BExpressionContext( "global", meta );
|
||||
rc.expctxWay = new BExpressionContext( "way", meta );
|
||||
rc.expctxNode = new BExpressionContext( "node", 1024, meta );
|
||||
rc.expctxWay = new BExpressionContext( "way", rc.serversizing ? 262144 : 4096, meta );
|
||||
rc.expctxNode = new BExpressionContext( "node", rc.serversizing ? 16384 : 1024, meta );
|
||||
|
||||
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
|
||||
|
||||
|
|
@ -504,7 +505,6 @@ public class RoutingEngine extends Thread
|
|||
if ( pe.cost >= costdelta )
|
||||
{
|
||||
pe.cost -= costdelta;
|
||||
pe.adjustedCost -= costdelta;
|
||||
|
||||
if ( guideTrack != null )
|
||||
{
|
||||
|
|
@ -559,7 +559,7 @@ public class RoutingEngine extends Thread
|
|||
|
||||
wp.radius = 1e9;
|
||||
OsmPath testPath = new OsmPath( null, startPath, link, null, guideTrack != null, routingContext );
|
||||
testPath.setAirDistanceCostAdjustment( (int)( nextNode.calcDistance( endPos ) * airDistanceCostFactor ) );
|
||||
testPath.airdistance = nextNode.calcDistance( endPos );
|
||||
if ( wp.radius < minradius )
|
||||
{
|
||||
bestPath = testPath;
|
||||
|
|
@ -593,10 +593,7 @@ public class RoutingEngine extends Thread
|
|||
|
||||
if ( wp != null ) wp.radius = 1e-5;
|
||||
|
||||
OsmPath testPath = new OsmPath( n1, startPath, link, null, guideTrack != null, routingContext );
|
||||
testPath.setAirDistanceCostAdjustment( 0 );
|
||||
|
||||
return testPath;
|
||||
return new OsmPath( n1, startPath, link, null, guideTrack != null, routingContext );
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -636,8 +633,6 @@ public class RoutingEngine extends Thread
|
|||
OsmPath startPath1 = getStartPath( start1, start2, startWp, endWp, sameSegmentSearch );
|
||||
OsmPath startPath2 = getStartPath( start2, start1, startWp, endWp, sameSegmentSearch );
|
||||
|
||||
int maxAdjCostFromQueue = 0;
|
||||
|
||||
// check for an INITIAL match with the cost-cutting-track
|
||||
if ( costCuttingTrack != null )
|
||||
{
|
||||
|
|
@ -655,8 +650,8 @@ public class RoutingEngine extends Thread
|
|||
synchronized( openSet )
|
||||
{
|
||||
openSet.clear();
|
||||
if ( startPath1.cost >= 0 ) openSet.add( startPath1 );
|
||||
if ( startPath2.cost >= 0 ) openSet.add( startPath2 );
|
||||
addToOpenset( startPath1 );
|
||||
addToOpenset( startPath2 );
|
||||
}
|
||||
while(!terminated)
|
||||
{
|
||||
|
|
@ -671,16 +666,10 @@ public class RoutingEngine extends Thread
|
|||
OsmPath path = null;
|
||||
synchronized( openSet )
|
||||
{
|
||||
if ( openSet.size() == 0 ) break;
|
||||
path = openSet.first();
|
||||
openSet.remove( path );
|
||||
path = openSet.popLowestKeyValue();
|
||||
}
|
||||
|
||||
if ( path.adjustedCost < maxAdjCostFromQueue && airDistanceCostFactor == 0.)
|
||||
{
|
||||
throw new RuntimeException( "assertion failed: path.adjustedCost < maxAdjCostFromQueue: " + path.adjustedCost + "<" + maxAdjCostFromQueue );
|
||||
}
|
||||
maxAdjCostFromQueue = path.adjustedCost;
|
||||
if ( path == null ) break;
|
||||
if ( path.airdistance == -1 ) continue;
|
||||
|
||||
if ( matchPath != null && fastPartialRecalc && firstMatchCost < 500 && path.cost > 30L*firstMatchCost )
|
||||
{
|
||||
|
|
@ -740,8 +729,7 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
|
||||
// recheck cutoff before doing expensive stuff
|
||||
int airDistance2 = currentNode.calcDistance( endPos );
|
||||
if ( path.cost + airDistance2 > maxTotalCost + 10 )
|
||||
if ( path.cost + path.airdistance > maxTotalCost + 10 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -824,18 +812,14 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
if ( otherPath != path )
|
||||
{
|
||||
synchronized( openSet )
|
||||
{
|
||||
openSet.remove( otherPath );
|
||||
}
|
||||
otherPath.airdistance = -1; // invalidate the entry in the open set
|
||||
}
|
||||
}
|
||||
if ( bestPath != null )
|
||||
{
|
||||
int airDistance = isFinalLink ? 0 : nextNode.calcDistance( endPos );
|
||||
bestPath.setAirDistanceCostAdjustment( (int)( airDistance * airDistanceCostFactor ) );
|
||||
bestPath.airdistance = isFinalLink ? 0 : nextNode.calcDistance( endPos );
|
||||
|
||||
if ( isFinalLink || bestPath.cost + airDistance <= maxTotalCost + 10 )
|
||||
if ( isFinalLink || bestPath.cost + bestPath.airdistance <= maxTotalCost + 10 )
|
||||
{
|
||||
// add only if this may beat an existing path for that link
|
||||
OsmLinkHolder dominator = link.firstlinkholder;
|
||||
|
|
@ -854,7 +838,7 @@ public class RoutingEngine extends Thread
|
|||
link.addLinkHolder( bestPath );
|
||||
synchronized( openSet )
|
||||
{
|
||||
openSet.add( bestPath );
|
||||
addToOpenset( bestPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -869,6 +853,14 @@ public class RoutingEngine extends Thread
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addToOpenset( OsmPath path )
|
||||
{
|
||||
if ( path.cost >= 0 )
|
||||
{
|
||||
openSet.add( path.cost + (int)(path.airdistance*airDistanceCostFactor), path );
|
||||
}
|
||||
}
|
||||
|
||||
private void preloadPosition( OsmNode n, int minRingWidth, int minCount )
|
||||
{
|
||||
|
|
@ -991,7 +983,16 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
synchronized( openSet )
|
||||
{
|
||||
return openSet.getExtract();
|
||||
List<OsmPath> extract = openSet.getExtract();
|
||||
int[] res = new int[extract.size() * 2];
|
||||
int i = 0;
|
||||
for( OsmPath p : extract )
|
||||
{
|
||||
OsmNode n = p.getLink().targetNode;
|
||||
res[i++] = n.ilon;
|
||||
res[i++] = n.ilat;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1044,4 +1045,10 @@ public class RoutingEngine extends Thread
|
|||
{
|
||||
terminated = true;
|
||||
}
|
||||
|
||||
public boolean isTerminated()
|
||||
{
|
||||
return terminated;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue