performance patches

This commit is contained in:
Arndt 2014-12-28 08:03:27 +01:00
parent 176beba6f6
commit 46db0104e5
13 changed files with 469 additions and 280 deletions

View file

@ -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,

View 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;
}
}

View 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 );
}
}