forked from burmanm/gorilla-tsc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
af88f10
commit 76dff33
Showing
4 changed files
with
329 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
176 changes: 176 additions & 0 deletions
176
src/main/java/gr/aueb/compression/gorilla/LossyCompressor32.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package gr.aueb.compression.gorilla; | ||
|
||
import fi.iki.yak.ts.compression.gorilla.BitOutput; | ||
|
||
/** | ||
* Implements the time series compression as described in the Facebook's Gorilla Paper. Value compression | ||
* is for floating points only. | ||
* | ||
* @author Michael Burman | ||
*/ | ||
public class LossyCompressor32 { | ||
|
||
private int storedLeadingZeros = Integer.MAX_VALUE; | ||
private int storedTrailingZeros = 0; | ||
private int storedVal = 0; | ||
private boolean first = true; | ||
private int size; | ||
private int cases[]; | ||
private float trailingDiff; | ||
private float leadingDiff; | ||
|
||
|
||
private BitOutput out; | ||
private int logOfError; | ||
|
||
public LossyCompressor32(BitOutput output, int logOfError) { | ||
this.out = output; | ||
this.size = 0; | ||
this.logOfError = logOfError; | ||
int cases[] = {0, 0, 0}; | ||
this.cases = cases; | ||
this.trailingDiff = 0; | ||
this.leadingDiff = 0; | ||
} | ||
|
||
/** | ||
* Adds a new long value to the series. Note, values must be inserted in order. | ||
* | ||
* @param timestamp Timestamp which is inside the allowed time block (default 24 hours with millisecond precision) | ||
* @param value next floating point value in the series | ||
*/ | ||
public void addValue(int value) { | ||
if(first) { | ||
writeFirst(value); | ||
} else { | ||
compressValue(value); | ||
} | ||
} | ||
|
||
/** | ||
* Adds a new double value to the series. Note, values must be inserted in order. | ||
* | ||
* @param timestamp Timestamp which is inside the allowed time block (default 24 hours with millisecond precision) | ||
* @param value next floating point value in the series | ||
*/ | ||
public void addValue(float value) { | ||
if(first) { | ||
writeFirst(Float.floatToRawIntBits(value)); | ||
} else { | ||
compressValue(Float.floatToRawIntBits(value)); | ||
} | ||
} | ||
|
||
private void writeFirst(int value) { | ||
first = false; | ||
storedVal = value; | ||
out.writeBits(storedVal, 32); | ||
size += 32; | ||
} | ||
|
||
/** | ||
* Closes the block and writes the remaining stuff to the BitOutput. | ||
*/ | ||
public void close() { | ||
addValue(Float.NaN); | ||
out.skipBit(); | ||
out.flush(); | ||
} | ||
|
||
private void compressValue(int value) { | ||
// TODO Fix already compiled into a big method | ||
int integerDigits = (value << 1 >>> 24) - 127; | ||
int space = 23 + this.logOfError - integerDigits; | ||
|
||
if (space > 0) { | ||
value = value >> space << space; | ||
value = value | (storedVal & (2^space - 1)); | ||
} | ||
|
||
int xor = storedVal ^ value; | ||
|
||
if(xor == 0) { | ||
// Write 0 | ||
cases[0] += 1; | ||
out.skipBit(); | ||
size += 1; | ||
} else { | ||
int leadingZeros = Integer.numberOfLeadingZeros(xor); | ||
int trailingZeros = Integer.numberOfTrailingZeros(xor); | ||
|
||
// Check overflow of leading? Can't be 32! | ||
if(leadingZeros >= 16) { | ||
leadingZeros = 15; | ||
} | ||
|
||
// Store bit '1' | ||
out.writeBit(); | ||
size += 1; | ||
|
||
if(leadingZeros >= storedLeadingZeros && trailingZeros >= storedTrailingZeros) { | ||
cases[1] += 1; | ||
this.trailingDiff += trailingZeros - storedTrailingZeros; | ||
this.leadingDiff += leadingZeros - storedLeadingZeros; | ||
writeExistingLeading(xor); | ||
} else { | ||
cases[2] += 2; | ||
writeNewLeading(xor, leadingZeros, trailingZeros); | ||
} | ||
} | ||
|
||
storedVal = value; | ||
} | ||
|
||
/** | ||
* If there at least as many leading zeros and as many trailing zeros as previous value, control bit = 0 (type a) | ||
* store the meaningful XORed value | ||
* | ||
* @param xor XOR between previous value and current | ||
*/ | ||
private void writeExistingLeading(int xor) { | ||
out.skipBit(); | ||
int significantBits = 32 - storedLeadingZeros - storedTrailingZeros; | ||
out.writeBits(xor >>> storedTrailingZeros, significantBits); | ||
size += 1 + significantBits; | ||
} | ||
|
||
/** | ||
* store the length of the number of leading zeros in the next 5 bits | ||
* store length of the meaningful XORed value in the next 6 bits, | ||
* store the meaningful bits of the XORed value | ||
* (type b) | ||
* | ||
* @param xor XOR between previous value and current | ||
* @param leadingZeros New leading zeros | ||
* @param trailingZeros New trailing zeros | ||
*/ | ||
private void writeNewLeading(int xor, int leadingZeros, int trailingZeros) { | ||
out.writeBit(); | ||
out.writeBits(leadingZeros, 4); // Number of leading zeros in the next 4 bits | ||
|
||
int significantBits = 32 - leadingZeros - trailingZeros; | ||
out.writeBits(significantBits, 6); // Length of meaningful bits in the next 5 bits | ||
out.writeBits(xor >>> trailingZeros, significantBits); // Store the meaningful bits of XOR | ||
|
||
storedLeadingZeros = leadingZeros; | ||
storedTrailingZeros = trailingZeros; | ||
|
||
size += 1 + 4 + 5 + significantBits; | ||
} | ||
|
||
public int getSize() { | ||
return size; | ||
} | ||
|
||
public float getLeadingDiff() { | ||
return leadingDiff; | ||
} | ||
|
||
public float getTrailingDiff() { | ||
return trailingDiff; | ||
} | ||
|
||
public int[] getCases() { | ||
return cases; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters