提交 d4f22985 authored 作者: buckyballs's avatar buckyballs

Minor DiskFile summary optimization

BitField.setRange optimization
BitField methods made static for performance --     getAddress / getBitMask methods.  

Contains *ALL* suggested code changes, checked with buildRelease and "build test"
上级 2c4622ee
...@@ -209,16 +209,13 @@ public class DiskFile implements CacheWriter { ...@@ -209,16 +209,13 @@ public class DiskFile implements CacheWriter {
DataOutputStream out = new DataOutputStream(buff); DataOutputStream out = new DataOutputStream(buff);
int blocks = (int) ((file.length() - OFFSET) / BLOCK_SIZE); int blocks = (int) ((file.length() - OFFSET) / BLOCK_SIZE);
out.writeInt(blocks); out.writeInt(blocks);
for (int i = 0, x = 0; i < blocks / 8; i++) { final int end = blocks/8;
int mask = 0; byte[] tempBuff = new byte[end];
for (int j = 0; j < 8; j++) { for (int i = 0; i < end; i++) {
if (used.get(x)) { tempBuff[i] = (byte) (used.getByte(i << 3) & 255);
mask |= 1 << j;
}
x++;
}
out.write(mask);
} }
out.write(tempBuff, 0, tempBuff.length);
tempBuff = null;
out.writeInt(pageOwners.size()); out.writeInt(pageOwners.size());
ObjectArray<Storage> storages = ObjectArray.newInstance(); ObjectArray<Storage> storages = ObjectArray.newInstance();
for (int i = 0; i < pageOwners.size(); i++) { for (int i = 0; i < pageOwners.size(); i++) {
...@@ -300,16 +297,18 @@ public class DiskFile implements CacheWriter { ...@@ -300,16 +297,18 @@ public class DiskFile implements CacheWriter {
return; return;
} }
stage++; stage++;
byte[] temp = new byte[b2];
in.readFully(temp);
if (init) { if (init) {
for (int x = 0; x < b2; x += 8) { for (int x = 0; x < b2; x += 8) {
int mask = in.read(); int mask = temp[x];
if (mask != used.getByte(x)) { if (mask != used.getByte(x)) {
Message.throwInternalError("Redo failure, block: " + x + " expected: " + used.getByte(x) + " got: " + mask); Message.throwInternalError("Redo failure, block: " + x + " expected: " + used.getByte(x) + " got: " + mask);
} }
} }
} else { } else {
for (int x = 0; x < b2; x += 8) { for (int x = 0; x < b2; x += 8) {
int mask = in.read(); int mask = temp[x];
used.setByte(x, mask); used.setByte(x, mask);
} }
} }
...@@ -707,7 +706,6 @@ public class DiskFile implements CacheWriter { ...@@ -707,7 +706,6 @@ public class DiskFile implements CacheWriter {
} }
} }
} }
/** /**
* Called after a session deleted a row. This sets the last uncommitted * Called after a session deleted a row. This sets the last uncommitted
* delete id in the session. This is used to make sure empty space is not * delete id in the session. This is used to make sure empty space is not
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Initial Developer: H2 Group * Initial Developer: H2 Group
*/ */
package org.h2.util; package org.h2.util;
import java.util.Arrays;
/** /**
* A list of bits. * A list of bits.
...@@ -159,11 +160,13 @@ public class BitField { ...@@ -159,11 +160,13 @@ public class BitField {
data[addr] &= ~getBitMask(i); data[addr] &= ~getBitMask(i);
} }
private int getAddress(int i) { // this is static to encourage compiler to inline it
private static int getAddress(int i) {
return i >> ADDRESS_BITS; return i >> ADDRESS_BITS;
} }
private long getBitMask(int i) { // this is static to encourage compiler to inline it
private static long getBitMask(int i) {
return 1L << (i & ADDRESS_MASK); return 1L << (i & ADDRESS_MASK);
} }
...@@ -185,24 +188,50 @@ public class BitField { ...@@ -185,24 +188,50 @@ public class BitField {
/** /**
* Enable or disable a number of bits. * Enable or disable a number of bits.
* *
* @author Samuel Van Oort
* @param start the index of the first bit to enable or disable * @param start the index of the first bit to enable or disable
* @param len the number of bits to enable or disable * @param len the number of bits to enable or disable
* @param value the new value * @param value the new value
*/ */
public void setRange(int start, int len, boolean value) { public void setRange(int start, int len, boolean value) {
// go backwards so that OutOfMemory happens int startIdx = getAddress(start);
// before some bytes are modified int endIdx = getAddress(start + len - 1);
for (int i = start + len - 1; i >= start; i--) { int end = start+len;
set(i, value);
// expand BitField if writing past end, unless clearing
// this prevents OutOfMemoryError mid-modify
int datalen = data.length;
if (endIdx >= datalen) {
if (!value && startIdx >= datalen) {
// trying to clear past end of set bits - nothing to do
return;
}
expandCapacity(endIdx);
} }
}
private void set(int i, boolean value) { long startMask = (~0L) << start;
long endMask = (~0L) >>> -end;
// if operating on one long, mask is combined
if (startIdx == endIdx) {
startMask &= endMask;
}
// set first long element in range
if (value) { if (value) {
set(i); data[startIdx] |= startMask;
} else { } else {
clear(i); data[startIdx] &= ~startMask;
} }
}
// work on additional elements only if needed
if (startIdx != endIdx) {
// set the last long element in range
if (value) {
data[endIdx] |= endMask;
} else {
data[endIdx] &= ~endMask;
}
// set longs fully in the range very quickly to all 1 or all 0
Arrays.fill(data, startIdx + 1, endIdx, value ? -1L : 0L);
}
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论