Refactored database data model to improve speed and reduce memory

consumption
This commit is contained in:
2018-11-05 18:21:54 +01:00
parent e687eef42c
commit 93fd192782
29 changed files with 360 additions and 471 deletions

View File

@ -0,0 +1,68 @@
package com.minres.scviewer.database;
public enum BitValue {
ZERO,
ONE,
X,
Z;
private static final BitValue[] ORDINAL_TABLE = BitValue.values();
public static BitValue fromChar(char c) {
switch (c) {
case '0':
return ZERO;
case '1':
return ONE;
case 'x':
case 'X':
return X;
case 'z':
case 'Z':
return Z;
default:
throw new NumberFormatException("unknown digit " + c);
}
}
public char toChar() {
switch (this) {
case ZERO:
return '0';
case ONE:
return '1';
case X:
return 'x';
case Z:
return 'z';
}
return ' '; // Unreachable?
}
public static BitValue fromInt(int i) {
if (i == 0) {
return ZERO;
} else {
return ONE;
}
}
public int toInt() {
return (this == ONE) ? 1 : 0;
}
public static BitValue fromOrdinal(int ord) {
return ORDINAL_TABLE[ord];
}
public int compare(BitValue other) {
if (this == ONE && other == ZERO) {
return 1;
} else if (this == ZERO && other == ONE) {
return -1;
} else {
// Either these are equal, or there is an X and Z, which match everything.
return 0;
}
}
}

View File

@ -12,31 +12,53 @@ package com.minres.scviewer.database;
public class BitVector {
public static final char VALUE_X = 'X';
public static final char VALUE_Z = 'Z';
public static final char VALUE_1 = '1';
public static final char VALUE_0 = '0';
private final int width;
private char[] value;
private int[] packedValues;
public BitVector(int netWidth) {
this.width=netWidth;
value = new char[netWidth];
for(int i=0; i<netWidth; i++) value[i]='0';
packedValues = new int[(netWidth+15)/16];
for(int i=0; i<packedValues.length; i++) packedValues[i]=0;
}
public void setValue(int i, char value) {
this.value[i]=value;
public void setValue(int i, BitValue value) {
int bitIndex = i*2;
int wordOffset = bitIndex >> 5;
int bitOffset = bitIndex & 31;
packedValues[wordOffset] &= ~(3 << bitOffset);
packedValues[wordOffset] |= value.ordinal() << bitOffset;
}
public char[] getValue() {
return value;
int bitOffset = 0;
int wordOffset = 0;
char[] res = new char[width];
// Copy values out of packed array
for (int i = 0; i < width; i++) {
int currentWord = (packedValues[wordOffset] >> bitOffset)&3;
res[width-i-1]=BitValue.fromInt(currentWord).toChar();
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
bitOffset = 0;
}
}
return res;
}
public void setValue(char[] value) {
this.value = value;
int bitIndex = width;
int wordOffset = bitIndex >> 4;
int bitOffset = (bitIndex * 2) % 32;
for (int i = Math.min(value.length, width) - 1; i >= 0; i--) {
packedValues[wordOffset] |= BitValue.fromChar(value[i]).ordinal() << bitOffset;
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
bitOffset = 0;
}
}
}
public int getWidth() {
@ -44,67 +66,101 @@ public class BitVector {
}
public String toString(){
return new String(value);
return new String(getValue());
}
public String toHexString(){
int resWidth=(width-1)/4+1;
char[] value=getValue();
char[] res = new char[resWidth];
for(int i=resWidth-1; i>=0; i--){
int digit=0;
for(int j=3; j>=0; j--){
if(value[4*i+j]==VALUE_X ||value[4*i+j]==VALUE_Z ){
res[i]=VALUE_X;
}
if(value[4*i+j]==VALUE_1)
BitValue val = BitValue.fromChar(value[4*i+j]);
switch(val) {
case X:
case Z:
res[i]=val.toChar();
continue;
case ONE:
digit+=1<<(3-j);
res[i]=Character.forDigit(digit, 16); //((digit < 10) ? '0' + digit : 'a' + digit -10)
break;
default:
break;
}
}
res[i]=Character.forDigit(digit, 16); //((digit < 10) ? '0' + digit : 'a' + digit -10)
}
return new String(res);
}
public long toUnsignedValue() {
long res = 0;
for(char c:value) {
int bitOffset = width * 2;
int wordOffset = bitOffset >> 5;
bitOffset &= 31;
int currentWord = packedValues[wordOffset] >> bitOffset;
// Copy values out of packed array
for (int i = 0; i < width; i++) {
res<<=1;
switch (c) {
case VALUE_1:
switch (currentWord & 3) {
case 1:
res++;
break;
case VALUE_X:
case VALUE_Z:
case 2:
case 3:
return 0;
default:
break;
}
}
return res;
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
currentWord = packedValues[wordOffset];
bitOffset = 0;
} else {
currentWord >>= 2;
}
}
return res;
}
public long toSignedValue() {
Boolean negative=null;
long res = 0;
for(char c:value) {
int bitOffset = width * 2;
int wordOffset = bitOffset >> 5;
bitOffset &= 31;
int currentWord = packedValues[wordOffset] >> bitOffset;
// Copy values out of packed array
for (int i = 0; i < width; i++) {
if(negative == null) {
switch (c) {
case VALUE_1: negative=true; break;
case VALUE_0: negative=false; break;
case VALUE_X:
case VALUE_Z: return 0;
switch (currentWord & 3) {
case 1: negative=true; break;
case 0: negative=false; break;
case 2:
case 3: return 0;
default:
}
} else {
res<<=1;
switch (c) {
case VALUE_1: if(!negative) res++; break;
case VALUE_0: if(negative) res++; break;
case VALUE_X:
case VALUE_Z: return 0;
switch (currentWord & 3) {
case 1: if(!negative) res++; break;
case 0: if(negative) res++; break;
case 2:
case 3: return 0;
default:
}
}
}
bitOffset += 2;
if (bitOffset == 32) {
wordOffset++;
currentWord = packedValues[wordOffset];
bitOffset = 0;
} else {
currentWord >>= 2;
}
}
return negative?-1*(res+1):res;
}
}

View File

@ -13,12 +13,14 @@ package com.minres.scviewer.database;
import java.util.NavigableMap;
public interface ISignal<T extends ISignalChange> extends IWaveform<T>{
public interface ISignal<T> extends IWaveform{
public NavigableMap<Long, T> getEvents();
public T getWaveformEventsAtTime(Long time);
public T getWaveformValueAtTime(Long time);
public T getWaveformEventsBeforeTime(Long time);
public T getWaveformValueBeforeTime(Long time);
public Class<?> getType();
}

View File

@ -1,15 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* MINRES Technologies GmbH - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChange extends IWaveformEvent {
}

View File

@ -1,17 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* MINRES Technologies GmbH - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChangeBit extends ISignalChange{
public char getValue();
}

View File

@ -1,17 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* MINRES Technologies GmbH - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChangeBitVector extends ISignalChange {
public BitVector getValue();
}

View File

@ -1,17 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* MINRES Technologies GmbH - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database;
public interface ISignalChangeReal extends ISignalChange{
public double getValue();
}

View File

@ -14,7 +14,7 @@ import java.util.Collection;
import java.util.List;
import java.util.NavigableMap;
public interface ITxStream<T extends ITxEvent> extends IWaveform<T> {
public interface ITxStream<T extends ITxEvent> extends IWaveform {
public List<ITxGenerator> getGenerators();

View File

@ -11,7 +11,7 @@
package com.minres.scviewer.database;
public interface IWaveform<T extends IWaveformEvent> extends IHierNode {
public interface IWaveform extends IHierNode {
public Long getId();
@ -19,6 +19,6 @@ public interface IWaveform<T extends IWaveformEvent> extends IHierNode {
public IWaveformDb getDb();
public Boolean equals(IWaveform<? extends IWaveformEvent> other);
public Boolean equals(IWaveform other);
}

View File

@ -18,9 +18,9 @@ public interface IWaveformDb extends IHierNode {
public Long getMaxTime();
public IWaveform<? extends IWaveformEvent> getStreamByName(String name);
public IWaveform getStreamByName(String name);
public List<IWaveform<?>> getAllWaves();
public List<IWaveform> getAllWaves();
public List<RelationType> getAllRelationTypes();

View File

@ -20,7 +20,7 @@ public interface IWaveformDbLoader {
public Long getMaxTime();
public List<IWaveform<? extends IWaveformEvent>> getAllWaves() ;
public List<IWaveform> getAllWaves() ;
public Collection<RelationType> getAllRelationTypes() ;

View File

@ -1,46 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 MINRES Technologies GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* MINRES Technologies GmbH - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database;
public class SignalChange implements IWaveformEvent {
Long time;
public SignalChange() {
time=0L;
}
public SignalChange(Long time) {
super();
this.time = time;
}
@Override
public int compareTo(IWaveformEvent o) {
return time.compareTo(o.getTime());
}
@Override
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
@Override
public IWaveformEvent duplicate() throws CloneNotSupportedException {
return (IWaveformEvent) this.clone();
}
}

View File

@ -41,7 +41,7 @@ public class WaveformDb extends HierNode implements IWaveformDb {
private List<RelationType> relationTypes;
private Map<String, IWaveform<?>> waveforms;
private Map<String, IWaveform> waveforms;
private Long maxTime;
@ -61,7 +61,7 @@ public class WaveformDb extends HierNode implements IWaveformDb {
public WaveformDb() {
super();
waveforms = new HashMap<String, IWaveform<?>>();
waveforms = new HashMap<String, IWaveform>();
relationTypes=new ArrayList<>();
maxTime=0L;
}
@ -72,20 +72,20 @@ public class WaveformDb extends HierNode implements IWaveformDb {
}
@Override
public IWaveform<? extends IWaveformEvent> getStreamByName(String name) {
public IWaveform getStreamByName(String name) {
return waveforms.get(name);
}
@Override
public List<IWaveform<?>> getAllWaves() {
return new ArrayList<IWaveform<?>>(waveforms.values());
public List<IWaveform> getAllWaves() {
return new ArrayList<IWaveform>(waveforms.values());
}
@Override
public boolean load(File inp) throws Exception {
for(IWaveformDbLoader loader:loaders){
if(loader.load(this, inp)){
for(IWaveform<?> w:loader.getAllWaves()){
for(IWaveform w:loader.getAllWaves()){
waveforms.put(w.getFullName(),w);
}
if(loader.getMaxTime()>maxTime){
@ -125,8 +125,8 @@ public class WaveformDb extends HierNode implements IWaveformDb {
private void buildHierarchyNodes() throws InputFormatException{
childNodes= new ArrayList<IHierNode>();
for(IWaveform<?> stream:getAllWaves()){
updateMaxTime(stream);
for(IWaveform stream:getAllWaves()){
//updateMaxTime(stream);
String[] hier = stream.getName().split("\\.");
IHierNode node = this;
List<String> path=new LinkedList<String>();
@ -169,16 +169,6 @@ public class WaveformDb extends HierNode implements IWaveformDb {
}
}
private void updateMaxTime(IWaveform<?> waveform) {
Long last=0L;
if(waveform instanceof ITxStream<?> && ((ITxStream<?>)waveform).getEvents().lastEntry()!=null)
last=((ITxStream<?>)waveform).getEvents().lastEntry().getKey();
else if(waveform instanceof ISignal<?> && ((ISignal<?>)waveform).getEvents().lastEntry()!=null)
last=((ISignal<?>)waveform).getEvents().lastEntry().getKey();
if(last>maxTime)
maxTime=last;
}
private static String join(Collection<?> col, String delim) {
StringBuilder sb = new StringBuilder();
Iterator<?> iter = col.iterator();