performance patches
This commit is contained in:
parent
176beba6f6
commit
46db0104e5
13 changed files with 469 additions and 280 deletions
|
|
@ -30,6 +30,19 @@ public class Crc32
|
|||
return crc;
|
||||
}
|
||||
|
||||
public static int crcWithInverseBit( byte[] ab, int inverseBitByteIndex )
|
||||
{
|
||||
int crc = 0xFFFFFFFF;
|
||||
int end = ab.length;
|
||||
for( int j=0; j<end; j++ )
|
||||
{
|
||||
byte b = ab[j];
|
||||
if ( j == inverseBitByteIndex ) b ^= 1;
|
||||
crc = (crc >>> 8) ^ crctable[(crc ^ b) & 0xff];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static int[] crctable = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
|
|
|
|||
258
brouter-util/src/main/java/btools/util/SortedHeap.java
Normal file
258
brouter-util/src/main/java/btools/util/SortedHeap.java
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Memory efficient Heap to get the lowest-key value
|
||||
* of a set of key-object pairs
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class SortedHeap<V>
|
||||
{
|
||||
private int[][] al;
|
||||
private int[] pa;
|
||||
private int[] lp; // the low pointers
|
||||
|
||||
private Object[][] vla; // value list array
|
||||
|
||||
protected static final int MAXLISTS = 31; // enough for size Integer.MAX_VALUE
|
||||
|
||||
private int size;
|
||||
private boolean isClear = false;
|
||||
|
||||
public SortedHeap()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lowest key value, or null if none
|
||||
*/
|
||||
public V popLowestKeyValue()
|
||||
{
|
||||
int minId = 0;
|
||||
int minIdx = -1;
|
||||
for ( int i=1;; i++ )
|
||||
{
|
||||
int[] ali = al[i];
|
||||
if ( ali == null ) break;
|
||||
int lpi = lp[i];
|
||||
if ( lpi < ali.length )
|
||||
{
|
||||
int currentId = ali[lpi];
|
||||
if ( minIdx < 0 || currentId < minId )
|
||||
{
|
||||
minIdx = i;
|
||||
minId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( minIdx == -1 ) return null;
|
||||
|
||||
int lp_minIdx = lp[minIdx]++;
|
||||
Object[] vla_minIdx = vla[minIdx];
|
||||
V res =(V)vla_minIdx[lp_minIdx];
|
||||
vla_minIdx[lp_minIdx] = null;
|
||||
size--;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* add a key value pair to the heap
|
||||
*
|
||||
* @param id the key to insert
|
||||
* @param value the value to insert object
|
||||
*/
|
||||
public void add( int key, V value )
|
||||
{
|
||||
isClear = false;
|
||||
size++;
|
||||
|
||||
// trivial shortcut if first array empty
|
||||
if ( lp[1] == 1)
|
||||
{
|
||||
al[1][0] = key;
|
||||
vla[1][0] = value;
|
||||
lp[1] = 0;
|
||||
return;
|
||||
}
|
||||
// trivial shortcut if second array empty
|
||||
if ( lp[2] > 0 )
|
||||
{
|
||||
int[] al2 = al[2];
|
||||
Object[] vla2 = vla[2];
|
||||
int key1;
|
||||
Object val1;
|
||||
if ( lp[2] == 2 )
|
||||
{
|
||||
key1 = al[1][0];
|
||||
val1 = vla[1][0];
|
||||
lp[1] = 1;
|
||||
}
|
||||
else // == 1
|
||||
{
|
||||
key1 = al2[1];
|
||||
val1 = vla2[1];
|
||||
}
|
||||
lp[2] = 0;
|
||||
if ( key1 < key )
|
||||
{
|
||||
al2[0] = key1;
|
||||
vla2[0] = val1;
|
||||
al2[1] = key;
|
||||
vla2[1] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
al2[1] = key1;
|
||||
vla2[1] = val1;
|
||||
al2[0] = key;
|
||||
vla2[0] = value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// put the new entry in the first array
|
||||
al[0][0] = key;
|
||||
vla[0][0] = value;
|
||||
|
||||
pa[0] = 1;
|
||||
pa[1] = 1;
|
||||
pa[2] = 2;
|
||||
|
||||
// determine the first array big enough to take them all
|
||||
int cnt = 4; // value count up to idx
|
||||
int idx = 3;
|
||||
int n = 4;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cnt += n-lp[idx];
|
||||
if ( cnt <= n ) break;
|
||||
pa[idx++] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
if ( idx == MAXLISTS )
|
||||
{
|
||||
throw new IllegalArgumentException( "overflow" );
|
||||
}
|
||||
|
||||
// create it if not existant
|
||||
if ( al[idx] == null )
|
||||
{
|
||||
al[idx] = new int[n];
|
||||
vla[idx] = new Object[n];
|
||||
}
|
||||
|
||||
int[] al_t = al[idx];
|
||||
Object[] vla_t = vla[idx];
|
||||
int lp_t = lp[idx];
|
||||
|
||||
// shift down content if any
|
||||
if ( lp_t < n )
|
||||
{
|
||||
System.arraycopy(al_t, lp_t, al_t, 0, n-lp_t);
|
||||
System.arraycopy(vla_t, lp_t, vla_t, 0, n-lp_t);
|
||||
}
|
||||
lp[idx] = 0;
|
||||
pa[idx] = n - lp_t;
|
||||
|
||||
|
||||
// now merge the contents of arrays 0...idx-1 into idx
|
||||
while ( cnt > 0 )
|
||||
{
|
||||
int maxId = 0;
|
||||
int maxIdx = -1;
|
||||
|
||||
for ( int i=0; i<=idx; i++ )
|
||||
{
|
||||
int p = pa[i];
|
||||
if ( p > lp[i] )
|
||||
{
|
||||
int currentId = al[i][p-1];
|
||||
if ( maxIdx < 0 || currentId > maxId )
|
||||
{
|
||||
maxIdx = i;
|
||||
maxId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current maximum found, copy to target array
|
||||
--n;
|
||||
al[idx][n] = maxId;
|
||||
vla[idx][n] = vla[maxIdx][pa[maxIdx]-1];
|
||||
|
||||
--cnt;
|
||||
--pa[maxIdx];
|
||||
}
|
||||
lp[idx] = n;
|
||||
while(--idx > 0) lp[idx] = al[idx].length;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
if ( !isClear )
|
||||
{
|
||||
isClear = true;
|
||||
size = 0;
|
||||
|
||||
// pointer array
|
||||
pa = new int[MAXLISTS];
|
||||
|
||||
lp = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new int[MAXLISTS][];
|
||||
al[0] = new int[1]; // make the first arrays
|
||||
al[1] = new int[1];
|
||||
al[2] = new int[2];
|
||||
|
||||
// same for the values
|
||||
vla = new Object[MAXLISTS][];
|
||||
vla[0] = new Object[1];
|
||||
vla[1] = new Object[1];
|
||||
vla[2] = new Object[2];
|
||||
|
||||
int n = 1;
|
||||
lp[0] = 0;
|
||||
for( int idx=1; idx < MAXLISTS; idx++ )
|
||||
{
|
||||
lp[idx] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<V> getExtract()
|
||||
{
|
||||
int div = size / 1000 + 1;
|
||||
|
||||
ArrayList<V> res = new ArrayList<V>(size / div );
|
||||
int cnt = 0;
|
||||
for ( int i=1;; i++ )
|
||||
{
|
||||
int[] ali = al[i];
|
||||
if ( ali == null ) break;
|
||||
int lpi = lp[i];
|
||||
Object[] vlai = vla[i];
|
||||
int n = ali.length;
|
||||
while ( lpi < n )
|
||||
{
|
||||
if ( (++cnt) % div == 0 )
|
||||
{
|
||||
res.add( (V)vla[i][lpi] );
|
||||
}
|
||||
lpi++;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
65
brouter-util/src/test/java/btools/util/SortedHeapTest.java
Normal file
65
brouter-util/src/test/java/btools/util/SortedHeapTest.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package btools.util;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SortedHeapTest
|
||||
{
|
||||
@Test
|
||||
public void sortedHeapTest1()
|
||||
{
|
||||
SortedHeap<String> sh = new SortedHeap<String>();
|
||||
Random rnd = new Random();
|
||||
for( int i = 0; i< 100000; i++ )
|
||||
{
|
||||
int val = rnd.nextInt( 1000000 );
|
||||
sh.add( val, "" + val );
|
||||
val = rnd.nextInt( 1000000 );
|
||||
sh.add( val, "" + val );
|
||||
sh.popLowestKeyValue();
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
int lastval = 0;
|
||||
for(;;)
|
||||
{
|
||||
String s = sh.popLowestKeyValue();
|
||||
if ( s == null ) break;
|
||||
cnt ++;
|
||||
int val = Integer.parseInt( s );
|
||||
Assert.assertTrue( "sorting test", val >= lastval );
|
||||
lastval = val;
|
||||
}
|
||||
Assert.assertTrue( "total count test", cnt == 100000 );
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortedHeapTest2()
|
||||
{
|
||||
SortedHeap<String> sh = new SortedHeap<String>();
|
||||
Random rnd = new Random();
|
||||
for( int i = 0; i< 100000; i++ )
|
||||
{
|
||||
sh.add( i, "" + i );
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
int expected = 0;
|
||||
for(;;)
|
||||
{
|
||||
String s = sh.popLowestKeyValue();
|
||||
if ( s == null ) break;
|
||||
cnt ++;
|
||||
int val = Integer.parseInt( s );
|
||||
Assert.assertTrue( "sequence test", val == expected );
|
||||
expected++;
|
||||
}
|
||||
Assert.assertTrue( "total count test", cnt == 100000 );
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue