added more cache reuse for better short-route performance
This commit is contained in:
parent
702c614dd3
commit
87ed332a56
3 changed files with 138 additions and 8 deletions
|
@ -24,6 +24,11 @@ final class MicroCache
|
||||||
private int aboffset;
|
private int aboffset;
|
||||||
private int ablength;
|
private int ablength;
|
||||||
|
|
||||||
|
// cache control: a virgin cache can be
|
||||||
|
// put to ghost state for later recovery
|
||||||
|
boolean virgin = true;
|
||||||
|
boolean ghost = false;
|
||||||
|
|
||||||
public MicroCache( OsmFile segfile, int lonIdx80, int latIdx80, byte[] iobuffer ) throws Exception
|
public MicroCache( OsmFile segfile, int lonIdx80, int latIdx80, byte[] iobuffer ) throws Exception
|
||||||
{
|
{
|
||||||
int lonDegree = lonIdx80/80;
|
int lonDegree = lonIdx80/80;
|
||||||
|
@ -40,6 +45,7 @@ final class MicroCache
|
||||||
|
|
||||||
if ( asize == 0 )
|
if ( asize == 0 )
|
||||||
{
|
{
|
||||||
|
ab = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( asize > iobuffer.length )
|
if ( asize > iobuffer.length )
|
||||||
|
@ -105,9 +111,19 @@ final class MicroCache
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDataSize()
|
||||||
|
{
|
||||||
|
return ab == null ? 0 : ab.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the value for "id",
|
* Set the internal reader (aboffset, ablength)
|
||||||
* Throw an exception if not contained in the map.
|
* to the body data for the given id
|
||||||
|
*
|
||||||
|
* @return true if id was found
|
||||||
|
*
|
||||||
|
* Throws an exception if that id was already requested
|
||||||
|
* as an early detector for identity problems
|
||||||
*/
|
*/
|
||||||
private boolean getAndClear( long id )
|
private boolean getAndClear( long id )
|
||||||
{
|
{
|
||||||
|
@ -148,7 +164,10 @@ final class MicroCache
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillNode( OsmNode node, OsmNodesMap nodesMap, DistanceChecker dc )
|
/**
|
||||||
|
* Fill a hollow node with it's body data
|
||||||
|
*/
|
||||||
|
public void fillNode( OsmNode node, OsmNodesMap nodesMap, DistanceChecker dc, boolean doCollect )
|
||||||
{
|
{
|
||||||
long id = node.getIdFromPos();
|
long id = node.getIdFromPos();
|
||||||
if ( getAndClear( id ) )
|
if ( getAndClear( id ) )
|
||||||
|
@ -156,8 +175,18 @@ final class MicroCache
|
||||||
node.parseNodeBody( this, ablength, nodesMap, dc );
|
node.parseNodeBody( this, ablength, nodesMap, dc );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( delcount > size / 2 ) // garbage collection
|
if ( doCollect && delcount > size / 2 ) // garbage collection
|
||||||
{
|
{
|
||||||
|
collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void collect()
|
||||||
|
{
|
||||||
|
if ( delcount > 0 )
|
||||||
|
{
|
||||||
|
virgin = false;
|
||||||
|
|
||||||
int nsize = size - delcount;
|
int nsize = size - delcount;
|
||||||
if ( nsize == 0 )
|
if ( nsize == 0 )
|
||||||
{
|
{
|
||||||
|
@ -197,6 +226,17 @@ final class MicroCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unGhost()
|
||||||
|
{
|
||||||
|
ghost = false;
|
||||||
|
delcount = 0;
|
||||||
|
delbytes = 0;
|
||||||
|
for( int i=0; i<size; i++ )
|
||||||
|
{
|
||||||
|
fapos[i] &= 0x7fffffff; // clear deleted flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<OsmNode> getPositions( OsmNodesMap nodesMap )
|
public List<OsmNode> getPositions( OsmNodesMap nodesMap )
|
||||||
{
|
{
|
||||||
ArrayList<OsmNode> positions = new ArrayList<OsmNode>();
|
ArrayList<OsmNode> positions = new ArrayList<OsmNode>();
|
||||||
|
|
|
@ -19,13 +19,16 @@ public final class NodesCache
|
||||||
private HashMap<String,PhysicalFile> fileCache;
|
private HashMap<String,PhysicalFile> fileCache;
|
||||||
private byte[] iobuffer;
|
private byte[] iobuffer;
|
||||||
|
|
||||||
private OsmFile[][] fileRows = new OsmFile[180][];
|
private OsmFile[][] fileRows;
|
||||||
private ArrayList<MicroCache> segmentList = new ArrayList<MicroCache>();
|
private ArrayList<MicroCache> segmentList = new ArrayList<MicroCache>();
|
||||||
|
|
||||||
public DistanceChecker distanceChecker;
|
public DistanceChecker distanceChecker;
|
||||||
|
|
||||||
public boolean oom_carsubset_hint = false;
|
public boolean oom_carsubset_hint = false;
|
||||||
|
|
||||||
|
private long cacheSum = 0;
|
||||||
|
private boolean garbageCollectionEnabled = false;
|
||||||
|
|
||||||
public NodesCache( String segmentDir, OsmNodesMap nodesMap, int lookupVersion, boolean carMode, NodesCache oldCache )
|
public NodesCache( String segmentDir, OsmNodesMap nodesMap, int lookupVersion, boolean carMode, NodesCache oldCache )
|
||||||
{
|
{
|
||||||
this.segmentDir = segmentDir;
|
this.segmentDir = segmentDir;
|
||||||
|
@ -38,14 +41,55 @@ public final class NodesCache
|
||||||
fileCache = oldCache.fileCache;
|
fileCache = oldCache.fileCache;
|
||||||
iobuffer = oldCache.iobuffer;
|
iobuffer = oldCache.iobuffer;
|
||||||
oom_carsubset_hint = oldCache.oom_carsubset_hint;
|
oom_carsubset_hint = oldCache.oom_carsubset_hint;
|
||||||
|
|
||||||
|
// re-use old, virgin caches
|
||||||
|
fileRows = oldCache.fileRows;
|
||||||
|
for( OsmFile[] fileRow : fileRows )
|
||||||
|
{
|
||||||
|
if ( fileRow == null ) continue;
|
||||||
|
for( OsmFile osmf : fileRow )
|
||||||
|
{
|
||||||
|
cacheSum += osmf.setGhostState();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fileCache = new HashMap<String,PhysicalFile>(4);
|
fileCache = new HashMap<String,PhysicalFile>(4);
|
||||||
|
fileRows = new OsmFile[180][];
|
||||||
iobuffer = new byte[65636];
|
iobuffer = new byte[65636];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the cache sum exceeded a threshold,
|
||||||
|
// clean all ghosts and enable garbage collection
|
||||||
|
private void checkEnableCacheCleaning()
|
||||||
|
{
|
||||||
|
if ( cacheSum < 200000 || garbageCollectionEnabled ) return;
|
||||||
|
|
||||||
|
for( int i=0; i<fileRows.length; i++ )
|
||||||
|
{
|
||||||
|
OsmFile[] fileRow = fileRows[i];
|
||||||
|
if ( fileRow == null ) continue;
|
||||||
|
int nghosts = 0;
|
||||||
|
for( OsmFile osmf : fileRow )
|
||||||
|
{
|
||||||
|
if ( osmf.ghost ) nghosts++;
|
||||||
|
else osmf.cleanAll();
|
||||||
|
}
|
||||||
|
if ( nghosts == 0 ) continue;
|
||||||
|
int j=0;
|
||||||
|
OsmFile[] frow = fileRows[fileRows.length-nghosts];
|
||||||
|
for( OsmFile osmf : fileRow )
|
||||||
|
{
|
||||||
|
if ( osmf.ghost ) continue;
|
||||||
|
frow[j++] = osmf;
|
||||||
|
}
|
||||||
|
fileRows[i] = frow;
|
||||||
|
}
|
||||||
|
garbageCollectionEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
public int loadSegmentFor( int ilon, int ilat )
|
public int loadSegmentFor( int ilon, int ilat )
|
||||||
{
|
{
|
||||||
MicroCache mc = getSegmentFor( ilon, ilat );
|
MicroCache mc = getSegmentFor( ilon, ilat );
|
||||||
|
@ -82,6 +126,7 @@ public final class NodesCache
|
||||||
newFileRow[ndegrees] = osmf;
|
newFileRow[ndegrees] = osmf;
|
||||||
fileRows[latDegree] = newFileRow;
|
fileRows[latDegree] = newFileRow;
|
||||||
}
|
}
|
||||||
|
osmf.ghost = false;
|
||||||
currentFileName = osmf.filename;
|
currentFileName = osmf.filename;
|
||||||
if ( osmf.microCaches == null )
|
if ( osmf.microCaches == null )
|
||||||
{
|
{
|
||||||
|
@ -93,10 +138,18 @@ public final class NodesCache
|
||||||
{
|
{
|
||||||
// nodesMap.removeCompleteNodes();
|
// nodesMap.removeCompleteNodes();
|
||||||
|
|
||||||
|
checkEnableCacheCleaning();
|
||||||
|
|
||||||
segment = new MicroCache( osmf, lonIdx80, latIdx80, iobuffer );
|
segment = new MicroCache( osmf, lonIdx80, latIdx80, iobuffer );
|
||||||
|
cacheSum += segment.getDataSize();
|
||||||
osmf.microCaches[subIdx] = segment;
|
osmf.microCaches[subIdx] = segment;
|
||||||
segmentList.add( segment );
|
segmentList.add( segment );
|
||||||
}
|
}
|
||||||
|
else if ( segment.ghost )
|
||||||
|
{
|
||||||
|
segment.unGhost();
|
||||||
|
segmentList.add( segment );
|
||||||
|
}
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
catch( RuntimeException re )
|
catch( RuntimeException re )
|
||||||
|
@ -119,7 +172,7 @@ public final class NodesCache
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
segment.fillNode( node, nodesMap, distanceChecker );
|
segment.fillNode( node, nodesMap, distanceChecker, garbageCollectionEnabled );
|
||||||
return !node.isHollow();
|
return !node.isHollow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ final class OsmFile
|
||||||
|
|
||||||
public String filename;
|
public String filename;
|
||||||
|
|
||||||
|
public boolean ghost = false;
|
||||||
|
|
||||||
public OsmFile( PhysicalFile rafile, int tileIndex, byte[] iobuffer ) throws Exception
|
public OsmFile( PhysicalFile rafile, int tileIndex, byte[] iobuffer ) throws Exception
|
||||||
{
|
{
|
||||||
if ( rafile != null )
|
if ( rafile != null )
|
||||||
|
@ -76,8 +78,43 @@ final class OsmFile
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close()
|
// set this OsmFile to ghost-state:
|
||||||
|
long setGhostState()
|
||||||
{
|
{
|
||||||
try { is.close(); } catch( IOException e ) { throw new RuntimeException( e ); }
|
long sum = 0;
|
||||||
|
ghost = true;
|
||||||
|
for( int i=0; i< microCaches.length; i++ )
|
||||||
|
{
|
||||||
|
MicroCache mc = microCaches[i];
|
||||||
|
if ( mc == null ) continue;
|
||||||
|
if ( mc.virgin )
|
||||||
|
{
|
||||||
|
mc.ghost = true;
|
||||||
|
sum += mc.getDataSize();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
microCaches[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanAll()
|
||||||
|
{
|
||||||
|
for( int i=0; i< microCaches.length; i++ )
|
||||||
|
{
|
||||||
|
MicroCache mc = microCaches[i];
|
||||||
|
if ( mc == null ) continue;
|
||||||
|
if ( mc.ghost )
|
||||||
|
{
|
||||||
|
microCaches[i] = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mc.collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue