提交 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 {
DataOutputStream out = new DataOutputStream(buff);
int blocks = (int) ((file.length() - OFFSET) / BLOCK_SIZE);
out.writeInt(blocks);
for (int i = 0, x = 0; i < blocks / 8; i++) {
int mask = 0;
for (int j = 0; j < 8; j++) {
if (used.get(x)) {
mask |= 1 << j;
}
x++;
}
out.write(mask);
final int end = blocks/8;
byte[] tempBuff = new byte[end];
for (int i = 0; i < end; i++) {
tempBuff[i] = (byte) (used.getByte(i << 3) & 255);
}
out.write(tempBuff, 0, tempBuff.length);
tempBuff = null;
out.writeInt(pageOwners.size());
ObjectArray<Storage> storages = ObjectArray.newInstance();
for (int i = 0; i < pageOwners.size(); i++) {
......@@ -300,16 +297,18 @@ public class DiskFile implements CacheWriter {
return;
}
stage++;
byte[] temp = new byte[b2];
in.readFully(temp);
if (init) {
for (int x = 0; x < b2; x += 8) {
int mask = in.read();
int mask = temp[x];
if (mask != used.getByte(x)) {
Message.throwInternalError("Redo failure, block: " + x + " expected: " + used.getByte(x) + " got: " + mask);
}
}
} else {
for (int x = 0; x < b2; x += 8) {
int mask = in.read();
int mask = temp[x];
used.setByte(x, mask);
}
}
......@@ -707,7 +706,6 @@ public class DiskFile implements CacheWriter {
}
}
}
/**
* 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
......
......@@ -5,6 +5,7 @@
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.util.Arrays;
/**
* A list of bits.
......@@ -159,11 +160,13 @@ public class BitField {
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;
}
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);
}
......@@ -185,24 +188,50 @@ public class BitField {
/**
* Enable or disable a number of bits.
*
* @author Samuel Van Oort
* @param start the index of the first bit to enable or disable
* @param len the number of bits to enable or disable
* @param value the new value
*/
public void setRange(int start, int len, boolean value) {
// go backwards so that OutOfMemory happens
// before some bytes are modified
for (int i = start + len - 1; i >= start; i--) {
set(i, value);
int startIdx = getAddress(start);
int endIdx = getAddress(start + len - 1);
int end = start+len;
// 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) {
set(i);
data[startIdx] |= startMask;
} 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论