more performance tuning
This commit is contained in:
parent
acb7c6b16f
commit
ea572ad47f
10 changed files with 357 additions and 165 deletions
|
@ -102,8 +102,7 @@ public final class MicroCache2 extends MicroCache
|
||||||
if ( debug ) System.out.println( "*** decoding node with links=" + links );
|
if ( debug ) System.out.println( "*** decoding node with links=" + links );
|
||||||
for( int li=0; li<links; li++ )
|
for( int li=0; li<links; li++ )
|
||||||
{
|
{
|
||||||
int startPointer = aboffset;
|
int sizeoffset = 0;
|
||||||
int sizeoffset = writeSizePlaceHolder();
|
|
||||||
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
|
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
|
||||||
|
|
||||||
int dlon_remaining;
|
int dlon_remaining;
|
||||||
|
@ -112,19 +111,25 @@ public final class MicroCache2 extends MicroCache
|
||||||
boolean isReverse = false;
|
boolean isReverse = false;
|
||||||
if ( nodeIdx != n ) // internal (forward-) link
|
if ( nodeIdx != n ) // internal (forward-) link
|
||||||
{
|
{
|
||||||
writeVarLengthSigned( dlon_remaining = alon[nodeIdx] - ilon );
|
dlon_remaining = alon[nodeIdx] - ilon;
|
||||||
writeVarLengthSigned( dlat_remaining = alat[nodeIdx] - ilat );
|
dlat_remaining = alat[nodeIdx] - ilat;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isReverse = bc.decodeBit();
|
isReverse = bc.decodeBit();
|
||||||
writeVarLengthSigned( dlon_remaining = extLonDiff.decodeSignedValue() );
|
dlon_remaining = extLonDiff.decodeSignedValue();
|
||||||
writeVarLengthSigned( dlat_remaining = extLatDiff.decodeSignedValue() );
|
dlat_remaining = extLatDiff.decodeSignedValue();
|
||||||
}
|
}
|
||||||
TagValueWrapper wayTags = wayTagCoder.decodeTagValueSet();
|
TagValueWrapper wayTags = wayTagCoder.decodeTagValueSet();
|
||||||
|
|
||||||
if ( wayTags != null )
|
if ( wayTags != null )
|
||||||
{
|
{
|
||||||
|
int startPointer = aboffset;
|
||||||
|
sizeoffset = writeSizePlaceHolder();
|
||||||
|
|
||||||
|
writeVarLengthSigned( dlon_remaining );
|
||||||
|
writeVarLengthSigned( dlat_remaining );
|
||||||
|
|
||||||
validNodes.set( n, true ); // mark source-node valid
|
validNodes.set( n, true ); // mark source-node valid
|
||||||
if ( nodeIdx != n ) // valid internal (forward-) link
|
if ( nodeIdx != n ) // valid internal (forward-) link
|
||||||
{
|
{
|
||||||
|
@ -132,9 +137,9 @@ public final class MicroCache2 extends MicroCache
|
||||||
finaldatasize += 1 + aboffset-startPointer; // reserve place for reverse
|
finaldatasize += 1 + aboffset-startPointer; // reserve place for reverse
|
||||||
validNodes.set( nodeIdx, true ); // mark target-node valid
|
validNodes.set( nodeIdx, true ); // mark target-node valid
|
||||||
}
|
}
|
||||||
|
writeModeAndDesc( isReverse, wayTags.data );
|
||||||
}
|
}
|
||||||
|
|
||||||
writeModeAndDesc( isReverse, wayTags == null ? null : wayTags.data );
|
|
||||||
if ( !isReverse ) // write geometry for forward links only
|
if ( !isReverse ) // write geometry for forward links only
|
||||||
{
|
{
|
||||||
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
||||||
|
@ -152,19 +157,19 @@ public final class MicroCache2 extends MicroCache
|
||||||
dlon_remaining -= dlon;
|
dlon_remaining -= dlon;
|
||||||
dlat_remaining -= dlat;
|
dlat_remaining -= dlat;
|
||||||
count--;
|
count--;
|
||||||
|
int elediff = transEleDiff.decodeSignedValue();
|
||||||
|
if ( wayTags != null )
|
||||||
|
{
|
||||||
writeVarLengthSigned( dlon );
|
writeVarLengthSigned( dlon );
|
||||||
writeVarLengthSigned( dlat );
|
writeVarLengthSigned( dlat );
|
||||||
writeVarLengthSigned( transEleDiff.decodeSignedValue() );
|
writeVarLengthSigned( elediff );
|
||||||
|
}
|
||||||
|
|
||||||
if ( matcher != null ) matcher.transferNode( ilontarget - dlon_remaining, ilattarget - dlat_remaining );
|
if ( matcher != null ) matcher.transferNode( ilontarget - dlon_remaining, ilattarget - dlat_remaining );
|
||||||
}
|
}
|
||||||
if ( matcher != null ) matcher.endNode( ilontarget, ilattarget );
|
if ( matcher != null ) matcher.endNode( ilontarget, ilattarget );
|
||||||
}
|
}
|
||||||
if ( wayTags == null )
|
if ( wayTags != null )
|
||||||
{
|
|
||||||
aboffset = startPointer; // not a valid link, delete it
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
injectSize( sizeoffset );
|
injectSize( sizeoffset );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 : 32768, meta );
|
rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 131072 : 32768, meta );
|
||||||
rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 4096, meta );
|
rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 4096 : 1024, meta );
|
||||||
|
|
||||||
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
|
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.TreeMap;
|
||||||
import btools.util.BitCoderContext;
|
import btools.util.BitCoderContext;
|
||||||
import btools.util.Crc32;
|
import btools.util.Crc32;
|
||||||
import btools.util.IByteArrayUnifier;
|
import btools.util.IByteArrayUnifier;
|
||||||
|
import btools.util.LruMap;
|
||||||
|
|
||||||
|
|
||||||
public abstract class BExpressionContext implements IByteArrayUnifier
|
public abstract class BExpressionContext implements IByteArrayUnifier
|
||||||
|
@ -49,10 +50,11 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
||||||
|
|
||||||
|
|
||||||
// hash-cache for function results
|
// hash-cache for function results
|
||||||
private byte[][] _arrayBitmap;
|
private CacheNode probeCacheNode = new CacheNode();
|
||||||
private int[] _arrayCrc;
|
private LruMap cache;
|
||||||
|
|
||||||
private int currentHashBucket = -1;
|
private VarWrapper probeVarSet = new VarWrapper();
|
||||||
|
private LruMap resultVarCache;
|
||||||
|
|
||||||
private List<BExpression> expressionList;
|
private List<BExpression> expressionList;
|
||||||
|
|
||||||
|
@ -60,20 +62,21 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
||||||
|
|
||||||
// build-in variable indexes for fast access
|
// build-in variable indexes for fast access
|
||||||
private int[] buildInVariableIdx;
|
private int[] buildInVariableIdx;
|
||||||
|
private int nBuildInVars;
|
||||||
|
|
||||||
private float[][] arrayBuildInVariablesCache;
|
private float[] currentVars;
|
||||||
private float[] hashBucketVars;
|
private int currentVarOffset;
|
||||||
|
|
||||||
|
protected void setInverseVars()
|
||||||
|
{
|
||||||
|
currentVarOffset = nBuildInVars;
|
||||||
|
}
|
||||||
|
|
||||||
abstract String[] getBuildInVariableNames();
|
abstract String[] getBuildInVariableNames();
|
||||||
|
|
||||||
protected final float getBuildInVariable( int idx )
|
protected final float getBuildInVariable( int idx )
|
||||||
{
|
{
|
||||||
return hashBucketVars[idx];
|
return currentVars[idx+currentVarOffset];
|
||||||
}
|
|
||||||
|
|
||||||
protected final float getInverseBuildInVariable( int idx )
|
|
||||||
{
|
|
||||||
return arrayBuildInVariablesCache[currentHashBucket | 1][idx];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int linenr;
|
private int linenr;
|
||||||
|
@ -102,9 +105,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
||||||
if ( Boolean.getBoolean( "disableExpressionCache" ) ) hashSize = 1;
|
if ( Boolean.getBoolean( "disableExpressionCache" ) ) hashSize = 1;
|
||||||
|
|
||||||
// create the expression cache
|
// create the expression cache
|
||||||
_arrayBitmap = new byte[hashSize][];
|
cache = new LruMap( 4*hashSize, hashSize );
|
||||||
_arrayCrc = new int[hashSize];
|
resultVarCache = new LruMap( 4096, 4096 );
|
||||||
arrayBuildInVariablesCache = new float[hashSize << 1][];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,116 +281,112 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
||||||
return "requests=" + requests + " requests2=" + requests2 + " cachemisses=" + cachemisses;
|
return "requests=" + requests + " requests2=" + requests2 + " cachemisses=" + cachemisses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public final byte[] unify( byte[] ab, int offset, int len )
|
public final byte[] unify( byte[] ab, int offset, int len )
|
||||||
{
|
{
|
||||||
int crc = Crc32.crc( ab, offset, len );
|
probeCacheNode.ab = null; // crc based cache lookup only
|
||||||
int hashSize = _arrayBitmap.length;
|
probeCacheNode.crc = Crc32.crc( ab, offset, len );
|
||||||
int idx = ( crc & 0xfffffff ) % hashSize;
|
|
||||||
byte[] abc = _arrayBitmap[idx];
|
CacheNode cn = (CacheNode)cache.get( probeCacheNode );
|
||||||
if ( abc != null && abc.length == len )
|
if ( cn != null )
|
||||||
{
|
{
|
||||||
int i = 0;
|
byte[] cab = cn.ab;
|
||||||
while (i < len)
|
if ( cab.length == len )
|
||||||
{
|
{
|
||||||
if ( ab[offset + i] != abc[i] )
|
for( int i=0; i<len; i++ )
|
||||||
|
{
|
||||||
|
if ( cab[i] != ab[i+offset] )
|
||||||
|
{
|
||||||
|
cn = null;
|
||||||
break;
|
break;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
if ( i == len )
|
}
|
||||||
return abc;
|
if ( cn != null )
|
||||||
|
{
|
||||||
|
return cn.ab;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
byte[] nab = new byte[len];
|
byte[] nab = new byte[len];
|
||||||
System.arraycopy( ab, offset, nab, 0, len );
|
System.arraycopy( ab, offset, nab, 0, len );
|
||||||
return nab;
|
return nab;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* evaluates the data in the given byte array
|
|
||||||
*
|
|
||||||
* @return true if the data is equivilant to the last calls data
|
|
||||||
*/
|
|
||||||
public final void evaluate( boolean inverseDirection, byte[] ab )
|
public final 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
|
||||||
|
|
||||||
// calc hash bucket from crc
|
probeCacheNode.ab = ab;
|
||||||
int crc = Crc32.crc( ab, 0, ab.length );
|
probeCacheNode.crc = Crc32.crc( ab, 0, ab.length );
|
||||||
int hashSize = _arrayBitmap.length;
|
|
||||||
int hashBucket2 = ( crc & 0xfffffff ) % hashSize;
|
|
||||||
int hashBucket01 = hashBucket2 << 1;
|
|
||||||
int hashBucket02 = hashBucket01 | 1;
|
|
||||||
int hashBucket = inverseDirection ? hashBucket02 : hashBucket01;
|
|
||||||
|
|
||||||
if ( hashBucket != currentHashBucket )
|
CacheNode cn = (CacheNode)cache.get( probeCacheNode );
|
||||||
|
if ( cn == null )
|
||||||
{
|
{
|
||||||
currentHashBucket = hashBucket;
|
|
||||||
hashBucketVars = arrayBuildInVariablesCache[hashBucket];
|
|
||||||
if ( hashBucketVars == null )
|
|
||||||
{
|
|
||||||
arrayBuildInVariablesCache[hashBucket01] = new float[buildInVariableIdx.length];
|
|
||||||
arrayBuildInVariablesCache[hashBucket02] = new float[buildInVariableIdx.length];
|
|
||||||
hashBucketVars = arrayBuildInVariablesCache[hashBucket];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( crc == _arrayCrc[hashBucket2] )
|
|
||||||
{
|
|
||||||
byte[] abBucket = _arrayBitmap[hashBucket2];
|
|
||||||
if ( ab == abBucket ) // fast identity check
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
requests2++;
|
|
||||||
|
|
||||||
// compare input value to hash bucket content
|
|
||||||
boolean hashBucketEquals = false;
|
|
||||||
int abLen = ab.length;
|
|
||||||
if ( abBucket != null && abBucket.length == abLen )
|
|
||||||
{
|
|
||||||
hashBucketEquals = true;
|
|
||||||
for ( int i = 0; i < abLen; i++ )
|
|
||||||
{
|
|
||||||
if ( abBucket[i] != ab[i] )
|
|
||||||
{
|
|
||||||
hashBucketEquals = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( hashBucketEquals )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cachemisses++;
|
cachemisses++;
|
||||||
|
|
||||||
_arrayBitmap[hashBucket2] = ab;
|
cn = (CacheNode)cache.removeLru();
|
||||||
_arrayCrc[hashBucket2] = crc;
|
if ( cn == null )
|
||||||
|
{
|
||||||
|
cn = new CacheNode();
|
||||||
|
}
|
||||||
|
cn.crc = probeCacheNode.crc;
|
||||||
|
cn.ab = ab;
|
||||||
|
cache.put( cn );
|
||||||
|
|
||||||
int nBuildInVars = buildInVariableIdx.length;
|
if ( probeVarSet.vars == null )
|
||||||
|
{
|
||||||
|
probeVarSet.vars = new float[2*nBuildInVars];
|
||||||
|
}
|
||||||
|
|
||||||
// forward direction
|
// forward direction
|
||||||
decode( lookupData, false, ab );
|
decode( lookupData, false, ab );
|
||||||
evaluate();
|
evaluateInto( probeVarSet.vars, 0 );
|
||||||
float[] vars = arrayBuildInVariablesCache[hashBucket01];
|
|
||||||
for ( int vi = 0; vi < nBuildInVars; vi++ )
|
|
||||||
{
|
|
||||||
int idx = buildInVariableIdx[vi];
|
|
||||||
vars[vi] = idx == -1 ? 0.f : variableData[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
// inverse direction
|
// inverse direction
|
||||||
lookupData[0] = 2; // inverse shortcut: reuse decoding
|
lookupData[0] = 2; // inverse shortcut: reuse decoding
|
||||||
|
evaluateInto( probeVarSet.vars, nBuildInVars );
|
||||||
|
|
||||||
|
probeVarSet.hash = Arrays.hashCode( probeVarSet.vars );
|
||||||
|
|
||||||
|
// unify the result variable set
|
||||||
|
VarWrapper vw = (VarWrapper)resultVarCache.get( probeVarSet );
|
||||||
|
if ( vw == null )
|
||||||
|
{
|
||||||
|
vw = (VarWrapper)resultVarCache.removeLru();
|
||||||
|
if ( vw == null )
|
||||||
|
{
|
||||||
|
vw = new VarWrapper();
|
||||||
|
}
|
||||||
|
vw.hash = probeVarSet.hash;
|
||||||
|
vw.vars = probeVarSet.vars;
|
||||||
|
probeVarSet.vars = null;
|
||||||
|
resultVarCache.put( vw );
|
||||||
|
}
|
||||||
|
cn.vars = vw.vars;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( ab == cn.ab ) requests2++;
|
||||||
|
|
||||||
|
cache.touch( cn );
|
||||||
|
}
|
||||||
|
|
||||||
|
currentVars = cn.vars;
|
||||||
|
currentVarOffset = inverseDirection ? nBuildInVars : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evaluateInto( float[] vars, int offset )
|
||||||
|
{
|
||||||
evaluate();
|
evaluate();
|
||||||
vars = arrayBuildInVariablesCache[hashBucket02];
|
|
||||||
for ( int vi = 0; vi < nBuildInVars; vi++ )
|
for ( int vi = 0; vi < nBuildInVars; vi++ )
|
||||||
{
|
{
|
||||||
int idx = buildInVariableIdx[vi];
|
int idx = buildInVariableIdx[vi];
|
||||||
vars[vi] = idx == -1 ? 0.f : variableData[idx];
|
vars[vi+offset] = idx == -1 ? 0.f : variableData[idx];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dumpStatistics()
|
public void dumpStatistics()
|
||||||
{
|
{
|
||||||
|
@ -650,7 +648,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier
|
||||||
|
|
||||||
// determine the build-in variable indices
|
// determine the build-in variable indices
|
||||||
String[] varNames = getBuildInVariableNames();
|
String[] varNames = getBuildInVariableNames();
|
||||||
buildInVariableIdx = new int[varNames.length];
|
nBuildInVars = varNames.length;
|
||||||
|
buildInVariableIdx = new int[nBuildInVars];
|
||||||
for( int vi=0; vi<varNames.length; vi++ )
|
for( int vi=0; vi<varNames.length; vi++ )
|
||||||
{
|
{
|
||||||
buildInVariableIdx[vi] = getVariableIdx( varNames[vi], false );
|
buildInVariableIdx[vi] = getVariableIdx( varNames[vi], false );
|
||||||
|
|
|
@ -32,8 +32,6 @@ public final class BExpressionContextWay extends BExpressionContext implements T
|
||||||
public float getPriorityClassifier() { return getBuildInVariable(9); }
|
public float getPriorityClassifier() { return getBuildInVariable(9); }
|
||||||
public float getClassifierMask() { return getBuildInVariable(10); }
|
public float getClassifierMask() { return getBuildInVariable(10); }
|
||||||
|
|
||||||
public float getInverseCostfactor() { return getInverseBuildInVariable(0); }
|
|
||||||
|
|
||||||
public BExpressionContextWay( BExpressionMetaData meta )
|
public BExpressionContextWay( BExpressionMetaData meta )
|
||||||
{
|
{
|
||||||
super( "way", meta );
|
super( "way", meta );
|
||||||
|
@ -56,7 +54,8 @@ public final class BExpressionContextWay extends BExpressionContext implements T
|
||||||
float minCostFactor = getCostfactor();
|
float minCostFactor = getCostfactor();
|
||||||
if ( minCostFactor >= 9999.f )
|
if ( minCostFactor >= 9999.f )
|
||||||
{
|
{
|
||||||
float reverseCostFactor = getInverseCostfactor();
|
setInverseVars();
|
||||||
|
float reverseCostFactor = getCostfactor();
|
||||||
if ( reverseCostFactor < minCostFactor )
|
if ( reverseCostFactor < minCostFactor )
|
||||||
{
|
{
|
||||||
minCostFactor = reverseCostFactor;
|
minCostFactor = reverseCostFactor;
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package btools.expressions;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import btools.util.LruMapNode;
|
||||||
|
|
||||||
|
public final class CacheNode extends LruMapNode
|
||||||
|
{
|
||||||
|
int crc;
|
||||||
|
byte[] ab;
|
||||||
|
float[] vars;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o )
|
||||||
|
{
|
||||||
|
CacheNode n = (CacheNode) o;
|
||||||
|
if ( crc != n.crc )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ab == null )
|
||||||
|
{
|
||||||
|
return true; // hack: null = crc match only
|
||||||
|
}
|
||||||
|
return Arrays.equals( ab, n.ab );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package btools.expressions;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import btools.util.LruMapNode;
|
||||||
|
|
||||||
|
public final class VarWrapper extends LruMapNode
|
||||||
|
{
|
||||||
|
int hash;
|
||||||
|
float[] vars;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o )
|
||||||
|
{
|
||||||
|
VarWrapper n = (VarWrapper) o;
|
||||||
|
if ( hash != n.hash )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Arrays.equals( vars, n.vars );
|
||||||
|
}
|
||||||
|
}
|
|
@ -107,23 +107,6 @@ public class ByteDataReader
|
||||||
return ( v & 1 ) == 0 ? v >> 1 : -(v >> 1 );
|
return ( v & 1 ) == 0 ? v >> 1 : -(v >> 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int readVarLengthUnsigned_old()
|
|
||||||
{
|
|
||||||
int v = 0;
|
|
||||||
int shift = 0;
|
|
||||||
for ( ;; )
|
|
||||||
{
|
|
||||||
byte b = ab[aboffset++];
|
|
||||||
v |= ( ( b & 0x7f ) << shift );
|
|
||||||
if ( ( b & 0x80 ) == 0 )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
shift += 7;
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final int readVarLengthUnsigned()
|
public final int readVarLengthUnsigned()
|
||||||
{
|
{
|
||||||
byte b;
|
byte b;
|
||||||
|
@ -135,15 +118,7 @@ public class ByteDataReader
|
||||||
if ( b >= 0 ) return v;
|
if ( b >= 0 ) return v;
|
||||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 21;
|
v |= ( (b=ab[aboffset++]) & 0x7f ) << 21;
|
||||||
if ( b >= 0 ) return v;
|
if ( b >= 0 ) return v;
|
||||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 28;
|
v |= ( (b=ab[aboffset++]) & 0xf ) << 28;
|
||||||
if ( b >= 0 ) return v;
|
|
||||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 35;
|
|
||||||
if ( b >= 0 ) return v;
|
|
||||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 42;
|
|
||||||
if ( b >= 0 ) return v;
|
|
||||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 49;
|
|
||||||
if ( b >= 0 ) return v;
|
|
||||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 56;
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class ByteDataWriter extends ByteDataReader
|
||||||
super ( byteArray );
|
super ( byteArray );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeInt( int v )
|
public final void writeInt( int v )
|
||||||
{
|
{
|
||||||
ab[aboffset++] = (byte)( (v >> 24) & 0xff );
|
ab[aboffset++] = (byte)( (v >> 24) & 0xff );
|
||||||
ab[aboffset++] = (byte)( (v >> 16) & 0xff );
|
ab[aboffset++] = (byte)( (v >> 16) & 0xff );
|
||||||
|
@ -21,7 +21,7 @@ public class ByteDataWriter extends ByteDataReader
|
||||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeLong( long v )
|
public final void writeLong( long v )
|
||||||
{
|
{
|
||||||
ab[aboffset++] = (byte)( (v >> 56) & 0xff );
|
ab[aboffset++] = (byte)( (v >> 56) & 0xff );
|
||||||
ab[aboffset++] = (byte)( (v >> 48) & 0xff );
|
ab[aboffset++] = (byte)( (v >> 48) & 0xff );
|
||||||
|
@ -33,35 +33,35 @@ public class ByteDataWriter extends ByteDataReader
|
||||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeBoolean( boolean v)
|
public final void writeBoolean( boolean v)
|
||||||
{
|
{
|
||||||
ab[aboffset++] = (byte)( v ? 1 : 0 );
|
ab[aboffset++] = (byte)( v ? 1 : 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeByte( int v )
|
public final void writeByte( int v )
|
||||||
{
|
{
|
||||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeShort( int v )
|
public final void writeShort( int v )
|
||||||
{
|
{
|
||||||
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
||||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write( byte[] sa )
|
public final void write( byte[] sa )
|
||||||
{
|
{
|
||||||
System.arraycopy( sa, 0, ab, aboffset, sa.length );
|
System.arraycopy( sa, 0, ab, aboffset, sa.length );
|
||||||
aboffset += sa.length;
|
aboffset += sa.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write( byte[] sa, int offset, int len )
|
public final void write( byte[] sa, int offset, int len )
|
||||||
{
|
{
|
||||||
System.arraycopy( sa, offset, ab, aboffset, len );
|
System.arraycopy( sa, offset, ab, aboffset, len );
|
||||||
aboffset += len;
|
aboffset += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeVarBytes( byte[] sa )
|
public final void writeVarBytes( byte[] sa )
|
||||||
{
|
{
|
||||||
if ( sa == null )
|
if ( sa == null )
|
||||||
{
|
{
|
||||||
|
@ -75,7 +75,7 @@ public class ByteDataWriter extends ByteDataReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeModeAndDesc( boolean isReverse, byte[] sa )
|
public final void writeModeAndDesc( boolean isReverse, byte[] sa )
|
||||||
{
|
{
|
||||||
int len = sa == null ? 0 : sa.length;
|
int len = sa == null ? 0 : sa.length;
|
||||||
int sizecode = len << 1 | ( isReverse ? 1 : 0 );
|
int sizecode = len << 1 | ( isReverse ? 1 : 0 );
|
||||||
|
@ -87,7 +87,7 @@ public class ByteDataWriter extends ByteDataReader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public byte[] toByteArray()
|
public final byte[] toByteArray()
|
||||||
{
|
{
|
||||||
byte[] c = new byte[aboffset];
|
byte[] c = new byte[aboffset];
|
||||||
System.arraycopy( ab, 0, c, 0, aboffset );
|
System.arraycopy( ab, 0, c, 0, aboffset );
|
||||||
|
@ -102,12 +102,12 @@ public class ByteDataWriter extends ByteDataReader
|
||||||
*
|
*
|
||||||
* @return the offset of the placeholder
|
* @return the offset of the placeholder
|
||||||
*/
|
*/
|
||||||
public int writeSizePlaceHolder()
|
public final int writeSizePlaceHolder()
|
||||||
{
|
{
|
||||||
return aboffset++;
|
return aboffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void injectSize( int sizeoffset )
|
public final void injectSize( int sizeoffset )
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int datasize = aboffset-sizeoffset-1;
|
int datasize = aboffset-sizeoffset-1;
|
||||||
|
@ -127,23 +127,47 @@ public class ByteDataWriter extends ByteDataReader
|
||||||
aboffset = sizeoffset + size + datasize;
|
aboffset = sizeoffset + size + datasize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int writeVarLengthSigned( int v )
|
public final void writeVarLengthSigned( int v )
|
||||||
{
|
{
|
||||||
return writeVarLengthUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 );
|
writeVarLengthUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int writeVarLengthUnsigned( int v )
|
public final void writeVarLengthUnsigned( int v )
|
||||||
{
|
|
||||||
int start = aboffset;
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
int i7 = v & 0x7f;
|
int i7 = v & 0x7f;
|
||||||
v >>= 7;
|
if ( ( v >>>= 7 ) == 0 )
|
||||||
if ( v != 0 ) i7 |= 0x80;
|
{
|
||||||
ab[aboffset++] = (byte)( i7 & 0xff );
|
ab[aboffset++] = (byte) ( i7 );
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
while( v != 0 );
|
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||||
return aboffset - start;
|
|
||||||
|
i7 = v & 0x7f;
|
||||||
|
if ( ( v >>>= 7 ) == 0 )
|
||||||
|
{
|
||||||
|
ab[aboffset++] = (byte) ( i7 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||||
|
|
||||||
|
i7 = v & 0x7f;
|
||||||
|
if ( ( v >>>= 7 ) == 0 )
|
||||||
|
{
|
||||||
|
ab[aboffset++] = (byte) ( i7 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||||
|
|
||||||
|
i7 = v & 0x7f;
|
||||||
|
if ( ( v >>>= 7 ) == 0 )
|
||||||
|
{
|
||||||
|
ab[aboffset++] = (byte) ( i7 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||||
|
|
||||||
|
ab[aboffset++] = (byte) ( v );
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size()
|
public int size()
|
||||||
|
|
121
brouter-util/src/main/java/btools/util/LruMap.java
Normal file
121
brouter-util/src/main/java/btools/util/LruMap.java
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
package btools.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Something like LinkedHashMap, but purpose build, less dynamic and memory efficient
|
||||||
|
*
|
||||||
|
* @author ab
|
||||||
|
*/
|
||||||
|
public final class LruMap
|
||||||
|
{
|
||||||
|
private int hashbins;
|
||||||
|
private int maxsize;
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
private LruMapNode lru;
|
||||||
|
private LruMapNode mru;
|
||||||
|
|
||||||
|
private LruMapNode[] binArray;
|
||||||
|
|
||||||
|
public LruMap( int bins, int size)
|
||||||
|
{
|
||||||
|
hashbins = bins;
|
||||||
|
maxsize = size;
|
||||||
|
binArray = new LruMapNode[hashbins];
|
||||||
|
}
|
||||||
|
|
||||||
|
public LruMapNode get( LruMapNode key )
|
||||||
|
{
|
||||||
|
int bin = ( key.hashCode() & 0xfffffff ) % hashbins;
|
||||||
|
|
||||||
|
LruMapNode e = binArray[bin];
|
||||||
|
while ( e != null )
|
||||||
|
{
|
||||||
|
if ( key.equals( e ) )
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
e = e.nextInBin;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// put e to the mru end of the queue
|
||||||
|
public void touch( LruMapNode e )
|
||||||
|
{
|
||||||
|
LruMapNode n = e.next;
|
||||||
|
LruMapNode p = e.previous;
|
||||||
|
|
||||||
|
if ( n == null )
|
||||||
|
{
|
||||||
|
return; // already at mru
|
||||||
|
}
|
||||||
|
n.previous = p;
|
||||||
|
if ( p != null )
|
||||||
|
{
|
||||||
|
p.next = n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lru = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
mru.next = e;
|
||||||
|
e.previous = mru;
|
||||||
|
e.next = null;
|
||||||
|
mru = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LruMapNode removeLru()
|
||||||
|
{
|
||||||
|
if ( size < maxsize )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
size--;
|
||||||
|
// unlink the lru from it's bin-queue
|
||||||
|
int bin = ( lru.hashCode() & 0xfffffff ) % hashbins;
|
||||||
|
LruMapNode e = binArray[bin];
|
||||||
|
if ( e == lru )
|
||||||
|
{
|
||||||
|
binArray[bin] = lru.nextInBin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while( e != null )
|
||||||
|
{
|
||||||
|
LruMapNode prev = e;
|
||||||
|
e = e.nextInBin;
|
||||||
|
if ( e == lru )
|
||||||
|
{
|
||||||
|
prev.nextInBin = lru.nextInBin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LruMapNode res = lru;
|
||||||
|
lru = lru.next;
|
||||||
|
lru.previous = null;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put( LruMapNode val )
|
||||||
|
{
|
||||||
|
int bin = ( val.hashCode() & 0xfffffff ) % hashbins;
|
||||||
|
val.nextInBin = binArray[bin];
|
||||||
|
binArray[bin] = val;
|
||||||
|
|
||||||
|
val.previous = mru;
|
||||||
|
val.next = null;
|
||||||
|
if ( mru == null )
|
||||||
|
{
|
||||||
|
lru = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mru.next = val;
|
||||||
|
}
|
||||||
|
mru = val;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
}
|
8
brouter-util/src/main/java/btools/util/LruMapNode.java
Normal file
8
brouter-util/src/main/java/btools/util/LruMapNode.java
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package btools.util;
|
||||||
|
|
||||||
|
public abstract class LruMapNode
|
||||||
|
{
|
||||||
|
LruMapNode nextInBin; // next entry for hash-bin
|
||||||
|
LruMapNode next; // next in lru sequence (towards mru)
|
||||||
|
LruMapNode previous; // previous in lru sequence (towards lru)
|
||||||
|
}
|
Loading…
Reference in a new issue