These changes reduce the time of DeltaEncoder by ~65% and DeltaDecoder
by ~40%, assuming using arrays that are several KB in size.
diff --git a/src/org/tukaani/xz/delta/DeltaCoder.java
b/src/org/tukaani/xz/delta/DeltaCoder.java
index d94eb66..ccb702d 100644xz/delta/DeltaCoder.java b/src/org/tukaani/xz/delt
--- a/src/org/tukaani/xz/delta/DeltaCoder.java
+++ b/src/org/tukaani/xz/delta/DeltaCoder.java
@@ -12,16 +12,15 @@ package org.tukaani.xz.delta;
abstract class DeltaCoder {
static final int DISTANCE_MIN = 1;
static final int DISTANCE_MAX = 256;
- static final int DISTANCE_MASK = DISTANCE_MAX - 1;
final int distance;
- final byte[] history = new byte[DISTANCE_MAX];
- int pos = 0;
+ final byte[] history;
DeltaCoder(int distance) {
if (distance < DISTANCE_MIN || distance > DISTANCE_MAX)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("invalid distance: " +
distance);
this.distance = distance;
+ this.history = new byte[distance];
}
}
diff --git a/src/org/tukaani/xz/delta/DeltaDecoder.java
b/src/org/tukaani/xz/delta/DeltaDecoder.java
index 154cbf3..d0bce28 100644
--- a/src/org/tukaani/xz/delta/DeltaDecoder.java
+++ b/src/org/tukaani/xz/delta/DeltaDecoder.java
@@ -15,10 +15,26 @@ public class DeltaDecoder extends DeltaCoder {
}
public void decode(byte[] buf, int off, int len) {
- int end = off + len;
- for (int i = off; i < end; ++i) {
- buf[i] += history[(distance + pos) & DISTANCE_MASK];
- history[pos-- & DISTANCE_MASK] = buf[i];
+ int i=0;
+ // first process from history buffer
+ for (int j = Math.min(len, distance); i < j; ++i) {
+ buf[off + i] += history[i];
+ }
+
+ // then process rest just within buf
+ for ( ; i<len; ++i) {
+ buf[off + i] += buf[off + i - distance];
+ }
+
+ // finally, populate the history buffer
+ if (len >= distance) {
+ System.arraycopy(buf, off + len - distance, history, 0, distance);
+ } else {
+ assert i == len;
+ // copy from end of buffer to beginning
+ System.arraycopy(history, i, history, 0, distance - i);
+ // now copy all of in to the end of the buffer
+ System.arraycopy(buf, off, history, distance - i, len);
}
}
}
diff --git a/src/org/tukaani/xz/delta/DeltaEncoder.java
b/src/org/tukaani/xz/delta/DeltaEncoder.java
index 17accce..ae8688e 100644
--- a/src/org/tukaani/xz/delta/DeltaEncoder.java
+++ b/src/org/tukaani/xz/delta/DeltaEncoder.java
@@ -15,10 +15,28 @@ public class DeltaEncoder extends DeltaCoder {
}
public void encode(byte[] in, int in_off, int len, byte[] out) {
- for (int i = 0; i < len; ++i) {
- byte tmp = history[(distance + pos) & DISTANCE_MASK];
- history[pos-- & DISTANCE_MASK] = in[in_off + i];
- out[i] = (byte)(in[in_off + i] - tmp);
+ int i=0;
+ // first deal with comparisons to the history buffer
+ for (int j=Math.min(len, distance); i<j; ++i) {
+ out[i] = (byte) (in[in_off + i] - history[i]);
+ }
+ // now fill the history buffer with the final (distance) bytes in
source
+ if (len >= distance) {
+ System.arraycopy(in, in_off + len - distance, history, 0,
distance);
+ } else {
+ assert i == len;
+ // copy from end of history buffer to beginning
+ System.arraycopy(history, i, history, 0, distance - i);
+ // now copy all of "in" to end of history buffer
+ System.arraycopy(in, in_off, history, distance - i, len);
+ }
+
+ for ( ; i < len; ++i) {
+ out[i] = (byte) (in[in_off + i] - in[in_off + i - distance]);
}
}
}