提交 165492ff authored 作者: Thomas Mueller's avatar Thomas Mueller

The CompressTool was not multithreading safe.

上级 6857dfdd
......@@ -18,7 +18,10 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>The compression algorithm "LZF" is now about 33% faster than before when compressing small block
<ul><li>The CompressTool was not multithreading safe. Because of this, the following database
operations where also not multithreading safe (even when using different databases): the SCRIPT command
(only when using compression), the COMPRESS function, and storing CLOB or BLOB data (only when compression is enabled).
</li><li>The compression algorithm "LZF" is now about 33% faster than before when compressing small block
(around 2 KB). It is much faster than Deflate, but the compression ratio is lower.
</li><li>Compressing large blocks of data didn't work when using the "Deflate" compression algorithm.
Compressing a lot of data could run out of heap memory.
......
......@@ -35,7 +35,6 @@ import org.h2.util.StringUtils;
*/
public class CompressTool {
private static final CompressTool INSTANCE = new CompressTool();
private static final int MAX_BUFFER_SIZE = 3 * Constants.IO_BUFFER_SIZE_COMPRESS;
private byte[] cachedBuffer;
......@@ -54,12 +53,14 @@ public class CompressTool {
}
/**
* Get the singleton.
* Get a new instance. Each instance uses a separate buffer, so multiple
* instances can be used concurrently. However each instance alone is not
* multithreading safe.
*
* @return the singleton
* @return a new instance
*/
public static CompressTool getInstance() {
return INSTANCE;
return new CompressTool();
}
/**
......@@ -87,7 +88,7 @@ public class CompressTool {
/**
* INTERNAL
*/
public synchronized int compress(byte[] in, int len, Compressor compress, byte[] out) {
public int compress(byte[] in, int len, Compressor compress, byte[] out) {
int newLen = 0;
out[0] = (byte) compress.getAlgorithm();
int start = 1 + writeInt(out, 1, len);
......
......@@ -518,7 +518,7 @@ public abstract class TestBase {
* @param actual the actual value
* @throws AssertionError if the values are not equal
*/
protected void assertEquals(byte[] expected, byte[] actual) {
public void assertEquals(byte[] expected, byte[] actual) {
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
if (expected[i] != actual[i]) {
......
......@@ -36,6 +36,7 @@ public class TestCompress extends TestBase {
}
public void test() throws Exception {
testMultiThreaded();
if (testPerformance) {
testDatabase();
}
......@@ -57,6 +58,44 @@ public class TestCompress extends TestBase {
testVariableEnd();
}
private void testMultiThreaded() throws Exception {
Thread[] threads = new Thread[3];
final boolean[] stop = new boolean[1];
final Exception[] ex = new Exception[1];
for (int i = 0; i < threads.length; i++) {
Thread t = new Thread() {
public void run() {
CompressTool tool = CompressTool.getInstance();
byte[] buff = new byte[1024];
Random r = new Random();
while (!stop[0]) {
r.nextBytes(buff);
try {
byte[] test = tool.expand(tool.compress(buff, "LZF"));
assertEquals(buff, test);
} catch (Exception e) {
ex[0] = e;
}
}
}
};
threads[i] = t;
t.start();
}
try {
Thread.sleep(1000);
stop[0] = true;
for (Thread t : threads) {
t.join();
}
} catch (InterruptedException e) {
// ignore
}
if (ex[0] != null) {
throw ex[0];
}
}
private void testVariableEnd() throws Exception {
CompressTool utils = CompressTool.getInstance();
StringBuilder buff = new StringBuilder();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论