some more cleanup and performance squeezing

This commit is contained in:
Arndt 2016-08-23 14:33:37 +02:00
parent f70dd3c3ac
commit 12d8cae46f
16 changed files with 265 additions and 212 deletions

View file

@ -22,7 +22,7 @@ public final class StatCoderContext extends BitCoderContext
*/ */
public void assignBits( String name ) public void assignBits( String name )
{ {
long bitpos = getBitPosition(); long bitpos = getWritingBitPosition();
if ( statsPerName == null ) if ( statsPerName == null )
{ {
statsPerName = new TreeMap<String, long[]>(); statsPerName = new TreeMap<String, long[]>();
@ -88,12 +88,7 @@ public final class StatCoderContext extends BitCoderContext
*/ */
public int decodeNoisyNumber( int noisybits ) public int decodeNoisyNumber( int noisybits )
{ {
int value = 0; int value = decodeBits( noisybits );
if ( noisybits > 0 )
{
int mask = 0xffffffff >>> ( 32 - noisybits );
value = decodeBounded( mask );
}
return value | ( decodeVarBits() << noisybits ); return value | ( decodeVarBits() << noisybits );
} }
@ -130,8 +125,7 @@ public final class StatCoderContext extends BitCoderContext
int value = 0; int value = 0;
if ( noisybits > 0 ) if ( noisybits > 0 )
{ {
int mask = 0xffffffff >>> ( 32 - noisybits ); value = decodeBits( noisybits ) - ( 1 << ( noisybits - 1 ) );
value = decodeBounded( mask ) - ( 1 << ( noisybits - 1 ) );
} }
int val2 = decodeVarBits() << noisybits; int val2 = decodeVarBits() << noisybits;
if ( val2 != 0 ) if ( val2 != 0 )

View file

@ -99,26 +99,33 @@ public final class TagValueCoder
node.child2 = decodeTree( bc, buffer, validator ); node.child2 = decodeTree( bc, buffer, validator );
return node; return node;
} }
BitCoderContext target = null; int startpos = bc.getReadingBitPosition();
boolean hasdata = false;
for ( ;; ) for ( ;; )
{ {
int delta = bc.decodeVarBits(); int delta = bc.decodeVarBits();
if ( target == null ) if ( !hasdata )
{ {
if ( delta == 0 ) if ( delta == 0 )
{
return null; return null;
target = new BitCoderContext( buffer ); }
target.encodeBit( false ); // dummy reverse bit hasdata = true;
} }
target.encodeVarBits( delta );
if ( delta == 0 ) if ( delta == 0 )
{
break; break;
int data = bc.decodeVarBits(); }
target.encodeVarBits( data ); bc.decodeVarBits();
} }
int len = target.getEncodedLength(); int endpos = bc.getReadingBitPosition();
byte[] res = new byte[len];
System.arraycopy( buffer, 0, res, 0, len ); int bitcount = endpos - startpos;
int bytecount = ( bitcount + 7 ) >> 3;
bc.setReadingBitPosition( startpos );
byte[] res = new byte[bytecount];
bc.copyBitsTo( res, bitcount );
int accessType = validator == null ? 2 : validator.accessType( res ); int accessType = validator == null ? 2 : validator.accessType( res );
if ( accessType > 0 ) if ( accessType > 0 )
@ -165,10 +172,6 @@ public final class TagValueCoder
return; return;
} }
BitCoderContext src = new BitCoderContext( data ); BitCoderContext src = new BitCoderContext( data );
if ( src.decodeBit() )
{
throw new IllegalArgumentException( "cannot encode reverse bit!" );
}
for ( ;; ) for ( ;; )
{ {
int delta = src.decodeVarBits(); int delta = src.decodeVarBits();

View file

@ -47,7 +47,7 @@ final class OsmPath implements OsmLinkHolder
public int originLon; public int originLon;
public int originLat; public int originLat;
// the costfactor of the segment just before this paths position // the classifier of the segment just before this paths position
public float lastClassifier; public float lastClassifier;
public MessageData message; public MessageData message;
@ -129,6 +129,37 @@ final class OsmPath implements OsmLinkHolder
MessageData msgData = recordMessageData ? new MessageData() : null; MessageData msgData = recordMessageData ? new MessageData() : null;
// evaluate the way tags
rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description );
// calculate the costfactor inputs
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
float turncostbase = rc.expctxWay.getTurncost();
float cfup = rc.expctxWay.getUphillCostfactor();
float cfdown = rc.expctxWay.getDownhillCostfactor();
float cf = rc.expctxWay.getCostfactor();
cfup = cfup == 0.f ? cf : cfup;
cfdown = cfdown == 0.f ? cf : cfdown;
// *** add initial cost if the classifier changed
float newClassifier = rc.expctxWay.getInitialClassifier();
if ( newClassifier == 0. )
{
newClassifier = (cfup + cfdown + cf)/3;
}
float classifierDiff = newClassifier - lastClassifier;
if ( classifierDiff > 0.0005 || classifierDiff < -0.0005 )
{
lastClassifier = newClassifier;
float initialcost = rc.expctxWay.getInitialcost();
int iicost = (int)initialcost;
if ( recordMessageData )
{
msgData.linkinitcost += iicost;
}
cost += iicost;
}
OsmTransferNode transferNode = link.decodeFirsttransfer( p1 ); OsmTransferNode transferNode = link.decodeFirsttransfer( p1 );
OsmNode targetNode = link.targetNode; OsmNode targetNode = link.targetNode;
for(;;) for(;;)
@ -152,10 +183,8 @@ final class OsmPath implements OsmLinkHolder
lat2 = transferNode.ilat; lat2 = transferNode.ilat;
ele2 = transferNode.selev; ele2 = transferNode.selev;
} }
boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description );
// if way description changed, store message // if recording, new MessageData for each section (needed for turn-instructions)
if ( recordMessageData && msgData.wayKeyValues != null ) if ( recordMessageData && msgData.wayKeyValues != null )
{ {
originElement.message = msgData; originElement.message = msgData;
@ -199,18 +228,16 @@ final class OsmPath implements OsmLinkHolder
} }
linkdisttotal += dist; linkdisttotal += dist;
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
// *** penalty for turning angles // *** penalty for turning angles
if ( !isTrafficBackbone && origin.originElement != null ) if ( !isTrafficBackbone && origin.originElement != null )
{ {
// penalty proportional to direction change // penalty proportional to direction change
double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
int turncost = (int)(cos * rc.expctxWay.getTurncost() + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty int actualturncost = (int)(cos * turncostbase + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty
cost += turncost; cost += actualturncost;
if ( recordMessageData ) if ( recordMessageData )
{ {
msgData.linkturncost += turncost; msgData.linkturncost += actualturncost;
msgData.turnangle = (float)rc.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); msgData.turnangle = (float)rc.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
} }
} }
@ -292,16 +319,8 @@ final class OsmPath implements OsmLinkHolder
ehbu = 0; ehbu = 0;
} }
// *** penalty for distance // get the effective costfactor (slope dependent)
float cfup = rc.expctxWay.getUphillCostfactor();
float cfdown = rc.expctxWay.getDownhillCostfactor();
float cf = rc.expctxWay.getCostfactor();
cfup = cfup == 0.f ? cf : cfup;
cfdown = cfdown == 0.f ? cf : cfdown;
float costfactor = cfup*upweight + cf*(1.f - upweight - downweight) + cfdown*downweight; float costfactor = cfup*upweight + cf*(1.f - upweight - downweight) + cfdown*downweight;
if ( isTrafficBackbone ) if ( isTrafficBackbone )
{ {
costfactor = 0.f; costfactor = 0.f;
@ -323,24 +342,6 @@ final class OsmPath implements OsmLinkHolder
int cost2 = cost < minDist ? minDist : cost; int cost2 = cost < minDist ? minDist : cost;
traffic += dist*rc.expctxWay.getTrafficSourceDensity()*Math.pow(cost2/10000.f,rc.trafficSourceExponent); traffic += dist*rc.expctxWay.getTrafficSourceDensity()*Math.pow(cost2/10000.f,rc.trafficSourceExponent);
} }
// *** add initial cost if the classifier changed
float newClassifier = rc.expctxWay.getInitialClassifier();
if ( newClassifier == 0. )
{
newClassifier = (cfup + cfdown + cf)/3;
}
float classifierDiff = newClassifier - lastClassifier;
if ( classifierDiff > 0.0005 || classifierDiff < -0.0005 )
{
lastClassifier = newClassifier;
float initialcost = rc.expctxWay.getInitialcost();
int iicost = (int)initialcost;
if ( recordMessageData )
{
msgData.linkinitcost += iicost;
}
cost += iicost;
}
if ( recordMessageData ) if ( recordMessageData )
{ {

View file

@ -63,8 +63,8 @@ public final class ProfileCache
BExpressionMetaData meta = new BExpressionMetaData(); BExpressionMetaData meta = new BExpressionMetaData();
BExpressionContextGlobal expctxGlobal = new BExpressionContextGlobal( meta ); BExpressionContextGlobal expctxGlobal = new BExpressionContextGlobal( meta );
rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 8192, meta ); rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 32768, meta );
rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 2048, meta ); rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 4096, meta );
meta.readMetaData( new File( profileDir, "lookups.dat" ) ); meta.readMetaData( new File( profileDir, "lookups.dat" ) );

View file

@ -12,10 +12,8 @@ import java.util.List;
import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContext;
import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay; import btools.expressions.BExpressionContextWay;
import btools.mapaccess.DistanceChecker;
import btools.mapaccess.OsmTransferNode;
public final class RoutingContext implements DistanceChecker public final class RoutingContext
{ {
public void setAlternativeIdx( int idx ) public void setAlternativeIdx( int idx )
{ {
@ -349,28 +347,4 @@ public final class RoutingContext implements DistanceChecker
return p; return p;
} }
@Override
public boolean isWithinRadius( int ilon0, int ilat0, OsmTransferNode firstTransfer, int ilon1, int ilat1 )
{
OsmNodeNamed wp = nogopoints.get(0);
double keepRadius = wp.radius;
try
{
int ilon = ilon0;
int ilat = ilat0;
for( OsmTransferNode trans = firstTransfer; trans != null; trans = trans.next )
{
calcDistance( ilon, ilat, trans.ilon, trans.ilat );
ilon = trans.ilon;
ilat = trans.ilat;
}
calcDistance( ilon, ilat, ilon1, ilat1 );
return wp.radius < keepRadius;
}
finally
{
wp.radius = keepRadius;
}
}
} }

View file

@ -226,10 +226,19 @@ public class RoutingEngine extends Thread
} }
finally finally
{ {
ProfileCache.releaseProfile( routingContext ); if ( hasInfo() && routingContext.expctxWay != null )
{
logInfo( "expression cache stats=" + routingContext.expctxWay.cacheStats() );
}
ProfileCache.releaseProfile( routingContext );
if ( nodesCache != null ) if ( nodesCache != null )
{ {
if ( hasInfo() && nodesCache != null )
{
logInfo( "NodesCache status before close=" + nodesCache.formatStatus() );
}
nodesCache.close(); nodesCache.close();
nodesCache = null; nodesCache = null;
} }
@ -544,6 +553,10 @@ public class RoutingEngine extends Thread
private void resetCache() private void resetCache()
{ {
if ( hasInfo() && nodesCache != null )
{
logInfo( "NodesCache status before reset=" + nodesCache.formatStatus() );
}
nodesMap = new OsmNodesMap(); nodesMap = new OsmNodesMap();
nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.carMode, routingContext.forceSecondaryData, nodesCache ); nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.carMode, routingContext.forceSecondaryData, nodesCache );
} }

View file

@ -49,12 +49,9 @@ public abstract class BExpressionContext
// hash-cache for function results // hash-cache for function results
private byte[][] _arrayBitmap; private byte[][] _arrayBitmap;
private boolean[] _arrayInverse;
private int[] _arrayCrc; private int[] _arrayCrc;
private int currentHashBucket = -1; private int currentHashBucket = -1;
private byte[] currentByteArray = null;
private boolean currentInverseDirection= false;
private List<BExpression> expressionList; private List<BExpression> expressionList;
@ -98,17 +95,10 @@ public abstract class BExpressionContext
if ( Boolean.getBoolean( "disableExpressionCache" ) ) hashSize = 1; if ( Boolean.getBoolean( "disableExpressionCache" ) ) hashSize = 1;
// create the expression cache
_arrayBitmap = new byte[hashSize][]; _arrayBitmap = new byte[hashSize][];
_arrayInverse = new boolean[hashSize];
_arrayCrc = new int[hashSize]; _arrayCrc = new int[hashSize];
// create the build-in variables cache
int nBuildInVars = getBuildInVariableNames().length;
arrayBuildInVariablesCache = new float[hashSize][]; arrayBuildInVariablesCache = new float[hashSize][];
for( int hi=0; hi<hashSize; hi++ )
{
arrayBuildInVariablesCache[hi] = new float[nBuildInVars];
}
} }
/** /**
@ -124,7 +114,6 @@ public abstract class BExpressionContext
{ {
// start with first bit hardwired ("reversedirection") // start with first bit hardwired ("reversedirection")
BitCoderContext ctx = new BitCoderContext( abBuf ); BitCoderContext ctx = new BitCoderContext( abBuf );
ctx.encodeBit( ld[0] != 0 );
int skippedTags = 0; int skippedTags = 0;
int nonNullTags= 0; int nonNullTags= 0;
@ -159,7 +148,7 @@ public abstract class BExpressionContext
// crosscheck: decode and compare // crosscheck: decode and compare
int[] ld2 = new int[lookupValues.size()]; int[] ld2 = new int[lookupValues.size()];
decode( ld2, false, ab ); decode( ld2, false, ab );
for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names for( int inum = 1; inum < lookupValues.size(); inum++ ) // loop over lookup names (except reverse dir)
{ {
if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab) ); if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab) );
} }
@ -185,7 +174,7 @@ public abstract class BExpressionContext
BitCoderContext ctx = new BitCoderContext(ab); BitCoderContext ctx = new BitCoderContext(ab);
// start with first bit hardwired ("reversedirection") // start with first bit hardwired ("reversedirection")
ld[0] = inverseDirection ^ ctx.decodeBit() ? 2 : 0; ld[0] = inverseDirection ? 2 : 0;
// all others are generic // all others are generic
int inum = 1; int inum = 1;
@ -270,72 +259,80 @@ public abstract class BExpressionContext
} }
} }
public long requests; private long requests;
public long requests2; private long requests2;
public long cachemisses; private long cachemisses;
public String cacheStats()
{
return "requests=" + requests + " requests2=" + requests2 + " cachemisses=" + cachemisses;
}
/** /**
* evaluates the data in the given byte array * evaluates the data in the given byte array
* *
* @return true if the data is equivilant to the last calls data * @return true if the data is equivilant to the last calls data
*/ */
public boolean evaluate( boolean inverseDirection, byte[] ab ) public void evaluate( boolean inverseDirection, byte[] ab )
{ {
requests ++; requests++;
lookupDataValid = false; // this is an assertion for a nasty pifall lookupDataValid = false; // this is an assertion for a nasty pifall
int inverseBitByteIndex = 0; // calc hash bucket from crc
int crc = Crc32.crcWithInverseBit( ab, inverseDirection );
int hashSize = _arrayBitmap.length;
currentHashBucket = ( crc & 0xfffffff ) % hashSize;
int nBuildInVars = buildInVariableIdx.length;
hashBucketVars = arrayBuildInVariablesCache[currentHashBucket];
if ( hashBucketVars == null )
{
hashBucketVars = new float[nBuildInVars];
arrayBuildInVariablesCache[currentHashBucket] = hashBucketVars;
}
// calc hash bucket from crc if ( crc == _arrayCrc[currentHashBucket] )
int lastHashBucket = currentHashBucket; {
int crc = Crc32.crcWithInverseBit(ab, inverseDirection ? inverseBitByteIndex : -1 ); byte[] abBucket = _arrayBitmap[currentHashBucket];
int hashSize = _arrayBitmap.length; if ( ab == abBucket ) // fast identity check
currentHashBucket = (crc & 0xfffffff) % hashSize; {
hashBucketVars = arrayBuildInVariablesCache[currentHashBucket]; return;
currentByteArray = ab; }
currentInverseDirection = inverseDirection; requests2++;
byte[] abBucket = _arrayBitmap[currentHashBucket];
boolean inverseBucket = _arrayInverse[currentHashBucket];
if ( ab == abBucket && inverseBucket == inverseDirection ) // fast identity check
{
return lastHashBucket == currentHashBucket;
}
requests2++;
// compare input value to hash bucket content // compare input value to hash bucket content
boolean hashBucketEquals = false; boolean hashBucketEquals = false;
if ( crc == _arrayCrc[currentHashBucket] ) int abLen = ab.length;
{ if ( abBucket != null && abBucket.length == abLen )
int abLen = ab.length; {
if ( abBucket != null && abBucket.length == ab.length ) hashBucketEquals = true;
{ for ( int i = 0; i < abLen; i++ )
hashBucketEquals = true; {
boolean isInverse = inverseDirection ^ inverseBucket; if ( abBucket[i] != ab[i] )
for( int i=0; i<abLen; i++ ) {
{ hashBucketEquals = false;
byte b = ab[i]; break;
if ( isInverse && i == inverseBitByteIndex ) b ^= 1; }
if ( abBucket[i] != b ) { hashBucketEquals = false; break; } }
} }
} if ( hashBucketEquals )
} {
if ( hashBucketEquals ) return lastHashBucket == currentHashBucket; return;
cachemisses++; }
}
_arrayBitmap[currentHashBucket] = currentByteArray; cachemisses++;
_arrayInverse[currentHashBucket] = currentInverseDirection;
_arrayCrc[currentHashBucket] = crc;
decode( lookupData, currentInverseDirection, currentByteArray ); _arrayBitmap[currentHashBucket] = ab;
evaluate( lookupData ); _arrayCrc[currentHashBucket] = crc;
for( int vi=0; vi<buildInVariableIdx.length; vi++ ) decode( lookupData, inverseDirection, ab );
{ evaluate( lookupData );
int idx = buildInVariableIdx[vi];
hashBucketVars[vi] = idx == -1 ? 0.f : variableData[idx];
}
return false; for ( int vi = 0; vi < nBuildInVars; vi++ )
{
int idx = buildInVariableIdx[vi];
hashBucketVars[vi] = idx == -1 ? 0.f : variableData[idx];
}
} }
public void dumpStatistics() public void dumpStatistics()

View file

@ -39,7 +39,7 @@ public class EncodeDecodeTest
byte[] description = expctxWay.encode(lookupData); byte[] description = expctxWay.encode(lookupData);
// calculate the cost factor from that description // calculate the cost factor from that description
expctxWay.evaluate( false, description ); expctxWay.evaluate( true, description ); // true = "reversedirection=yes" (not encoded in description anymore)
float costfactor = expctxWay.getCostfactor(); float costfactor = expctxWay.getCostfactor();
Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 ); Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 );

View file

@ -1,16 +0,0 @@
/**
* Container for routig configs
*
* @author ab
*/
package btools.mapaccess;
public interface DistanceChecker
{
/**
* Checks whether the given path is within a maximum distance
* known to the distance checker
* @return true if close enough
*/
boolean isWithinRadius( int ilon0, int ilat0, OsmTransferNode firstTransfer, int ilon1, int ilat1 );
}

View file

@ -42,6 +42,11 @@ public final class NodesCache
private long cacheSum = 0; private long cacheSum = 0;
private boolean garbageCollectionEnabled = false; private boolean garbageCollectionEnabled = false;
public String formatStatus()
{
return "collecting=" + garbageCollectionEnabled + " cacheSum=" + cacheSum;
}
public NodesCache( String segmentDir, OsmNodesMap nodesMap, BExpressionContextWay ctxWay, boolean carMode, boolean forceSecondaryData, public NodesCache( String segmentDir, OsmNodesMap nodesMap, BExpressionContextWay ctxWay, boolean carMode, boolean forceSecondaryData,
NodesCache oldCache ) NodesCache oldCache )
@ -91,7 +96,7 @@ public final class NodesCache
// clean all ghosts and enable garbage collection // clean all ghosts and enable garbage collection
private void checkEnableCacheCleaning() private void checkEnableCacheCleaning()
{ {
if ( cacheSum < 500000 || garbageCollectionEnabled ) if ( cacheSum < 3000000 || garbageCollectionEnabled )
return; return;
for ( int i = 0; i < fileRows.length; i++ ) for ( int i = 0; i < fileRows.length; i++ )

View file

@ -178,8 +178,7 @@ public class OsmNode implements OsmPos
OsmLink link = getCompatibleLink( linklon, linklat, isReverse, 2 ); OsmLink link = getCompatibleLink( linklon, linklat, isReverse, 2 );
if ( link == null ) // .. not found, then check the hollow nodes if ( link == null ) // .. not found, then check the hollow nodes
{ {
long targetNodeId = ( (long) linklon ) << 32 | linklat; OsmNode tn = hollowNodes.get( linklon, linklat ); // target node
OsmNode tn = hollowNodes.get( targetNodeId ); // target node
if ( tn == null ) // node not yet known, create a new hollow proxy if ( tn == null ) // node not yet known, create a new hollow proxy
{ {
tn = new OsmNode( linklon, linklat ); tn = new OsmNode( linklon, linklat );

View file

@ -26,10 +26,10 @@ public final class OsmNodesMap
* Get a node from the map * Get a node from the map
* @return the node for the given id if exist, else null * @return the node for the given id if exist, else null
*/ */
public OsmNode get( long id ) public OsmNode get( int ilon, int ilat )
{ {
testKey.ilon = (int)(id >> 32); testKey.ilon = ilon;
testKey.ilat = (int)(id & 0xffffffff); testKey.ilat = ilat;
return hmap.get( testKey ); return hmap.get( testKey );
} }
@ -48,13 +48,4 @@ public final class OsmNodesMap
return hmap.put( node, node ); return hmap.put( node, node );
} }
/**
* @return the number of nodes in that map
*/
public int size()
{
return hmap.size();
}
} }

View file

@ -69,7 +69,7 @@ public class TwinRoutingEngine extends RoutingEngine
System.out.println( "linksProcessed=" + router.linksProcessed + " linksReProcessed=" + router.linksReProcessed); System.out.println( "linksProcessed=" + router.linksProcessed + " linksReProcessed=" + router.linksReProcessed);
System.out.println( "skippedChained=" + router.skippedChained + " closedSkippedChained=" + router.closedSkippedChained); System.out.println( "skippedChained=" + router.skippedChained + " closedSkippedChained=" + router.closedSkippedChained);
System.out.println( "expCtxWay: requests: " + routingContext.expctxWay.requests + " requests2: " + routingContext.expctxWay.requests2 + " cache-misses: " + routingContext.expctxWay.cachemisses ); System.out.println( "expCtxWay: requests: " + routingContext.expctxWay.cacheStats() );
} }
} }

View file

@ -4,13 +4,16 @@ package btools.util;
public class BitCoderContext public class BitCoderContext
{ {
private byte[] ab; private byte[] ab;
private int idxMax;
private int idx = -1; private int idx = -1;
private int bm = 0x100; // byte mask private int bm = 0x100; // byte mask (write mode)
private int bits; // bits left in buffer (read mode)
private int b; private int b;
public BitCoderContext( byte[] ab ) public BitCoderContext( byte[] ab )
{ {
this.ab = ab; this.ab = ab;
idxMax = ab.length-1;
} }
/** /**
@ -39,18 +42,32 @@ public class BitCoderContext
/** /**
* @see #encodeVarBits * @see #encodeVarBits
*/ */
public final int decodeVarBits() public final int decodeVarBits2()
{ {
int range = 0; int range = 0;
int value = 0;
while (!decodeBit()) while (!decodeBit())
{ {
value += range + 1;
range = 2 * range + 1; range = 2 * range + 1;
} }
return value + decodeBounded( range ); return range + decodeBounded( range );
} }
public final int decodeVarBits()
{
int range = 1;
int cnt = 1;
fillBuffer();
while ((b & range) == 0)
{
range = (range << 1) | 1;
cnt++;
}
b >>>= cnt;
bits -= cnt;
return (range >>> 1) + ( cnt > 1 ? decodeBits( cnt-1 ) : 0 );
}
public final void encodeBit( boolean value ) public final void encodeBit( boolean value )
{ {
if ( bm == 0x100 ) if ( bm == 0x100 )
@ -65,13 +82,14 @@ public class BitCoderContext
public final boolean decodeBit() public final boolean decodeBit()
{ {
if ( bm == 0x100 ) if ( bits == 0 )
{ {
bm = 1; bits = 8;
b = ab[++idx]; b = ab[++idx] & 0xff;
} }
boolean value = ( ( b & bm ) != 0 ); boolean value = ( ( b & 1 ) != 0 );
bm <<= 1; b >>>= 1;
bits--;
return value; return value;
} }
@ -111,19 +129,46 @@ public class BitCoderContext
int im = 1; // integer mask int im = 1; // integer mask
while (( value | im ) <= max) while (( value | im ) <= max)
{ {
if ( bm == 0x100 ) if ( bits == 0 )
{ {
bm = 1; bits = 8;
b = ab[++idx]; b = ab[++idx] & 0xff;
} }
if ( ( b & bm ) != 0 ) if ( ( b & 1 ) != 0 )
value |= im; value |= im;
bm <<= 1; b >>>= 1;
bits--;
im <<= 1; im <<= 1;
} }
return value; return value;
} }
public final int decodeBits( int count )
{
if ( count == 0 )
{
return 0;
}
fillBuffer();
int mask = 0xffffffff >>> ( 32 - count );
int value = b & mask;
b >>>= count;
bits -= count;
return value;
}
private void fillBuffer()
{
while (bits < 24)
{
if ( idx < idxMax )
{
b |= (ab[++idx] & 0xff) << bits;
}
bits += 8;
}
}
/** /**
* @return the encoded length in bytes * @return the encoded length in bytes
*/ */
@ -135,7 +180,7 @@ public class BitCoderContext
/** /**
* @return the encoded length in bits * @return the encoded length in bits
*/ */
public final long getBitPosition() public final long getWritingBitPosition()
{ {
long bitpos = idx << 3; long bitpos = idx << 3;
int m = bm; int m = bm;
@ -147,4 +192,53 @@ public class BitCoderContext
return bitpos; return bitpos;
} }
public final int getReadingBitPosition()
{
return (idx << 3) + 8 - bits;
}
public final void setReadingBitPosition(int pos)
{
idx = pos >>> 3;
bits = (idx << 3) + 8 - pos;
b = ab[idx] & 0xff;
b >>>= (8-bits);
}
public final void copyBitsTo( byte[] dst, int bitcount )
{
int dstIdx = 0;
for(;;)
{
if ( bitcount > 8 )
{
if ( bits < 8 )
{
b |= (ab[++idx] & 0xff) << bits;
}
else
{
bits -= 8;
}
dst[dstIdx++] = (byte)b;
b >>>= 8;
bitcount -= 8;
}
else
{
if ( bits < bitcount )
{
b |= (ab[++idx] & 0xff) << bits;
bits += 8;
}
int mask = 0xff >>> ( 8 - bitcount );
dst[dstIdx] = (byte)(b & mask);
bits -= bitcount;
b >>>= bitcount;
break;
}
}
}
} }

View file

@ -30,17 +30,15 @@ public class Crc32
return crc; return crc;
} }
public static int crcWithInverseBit( byte[] ab, int inverseBitByteIndex ) public static int crcWithInverseBit( byte[] ab, boolean isInverse )
{ {
int crc = 0xFFFFFFFF; int crc = 0xFFFFFF ^ ( isInverse ? 0x990951ba : 0x706af48f ); // inverse is webbed into crc...
int end = ab.length; int end = ab.length;
for( int j=0; j<end; j++ ) for( int j=0; j<end; j++ )
{ {
byte b = ab[j]; crc = (crc >>> 8) ^ crctable[(crc ^ ab[j]) & 0xff];
if ( j == inverseBitByteIndex ) b ^= 1;
crc = (crc >>> 8) ^ crctable[(crc ^ b) & 0xff];
} }
return crc; return isInverse ? crc | 0x80000000 : crc & 0x7fffffff; // ... and set as high bit
} }
private static int[] crctable = { private static int[] crctable = {

View file

@ -19,7 +19,7 @@ public class BitCoderContextTest
for ( int i = 0; i < 1000; i++ ) for ( int i = 0; i < 1000; i++ )
{ {
int value = ctx.decodeVarBits(); int value = ctx.decodeVarBits();
Assert.assertTrue( "distance value mismatch", value == i ); Assert.assertTrue( "distance value mismatch i=" + i + "v=" + value, value == i );
} }
} }