Skip to content

Commit cfbfe13

Browse files
committed
slightly improved lz4 performance
1 parent 90e80ff commit cfbfe13

File tree

3 files changed

+31
-16
lines changed

3 files changed

+31
-16
lines changed

Diff for: clickhouse-client/src/main/java/com/clickhouse/client/stream/Lz4InputStream.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public class Lz4InputStream extends AbstractByteArrayInputStream {
2626
private final InputStream stream;
2727
private final byte[] header;
2828

29+
private byte[] compressedBlock;
30+
2931
private boolean readFully(byte[] b, int off, int len) throws IOException {
3032
int n = 0;
3133
while (n < len) {
@@ -61,7 +63,8 @@ protected int updateBuffer() throws IOException {
6163
// 4 bytes - size of uncompressed data
6264
int uncompressedSize = BinaryStreamUtils.toInt32(header, 21);
6365
int offset = 9;
64-
byte[] block = new byte[compressedSizeWithHeader];
66+
final byte[] block = compressedBlock.length >= compressedSizeWithHeader ? compressedBlock
67+
: (compressedBlock = new byte[compressedSizeWithHeader]);
6568
block[0] = header[16];
6669
BinaryStreamUtils.setInt32(block, 1, compressedSizeWithHeader);
6770
BinaryStreamUtils.setInt32(block, 5, uncompressedSize);
@@ -70,17 +73,17 @@ protected int updateBuffer() throws IOException {
7073
throw new IOException(ClickHouseUtils.format(ERROR_INCOMPLETE_READ, 0, compressedSizeWithHeader - offset));
7174
}
7275

73-
long[] real = ClickHouseCityHash.cityHash128(block, 0, block.length);
76+
long[] real = ClickHouseCityHash.cityHash128(block, 0, compressedSizeWithHeader);
7477
if (real[0] != BinaryStreamUtils.toInt64(header, 0) || real[1] != BinaryStreamUtils.toInt64(header, 8)) {
7578
throw new IOException("Checksum doesn't match: corrupted data.");
7679
}
7780

78-
buffer = new byte[uncompressedSize];
79-
decompressor.decompress(block, offset, buffer, 0, uncompressedSize);
81+
final byte[] buf = buffer.length >= uncompressedSize ? buffer : (buffer = new byte[uncompressedSize]);
82+
decompressor.decompress(block, offset, buf, 0, uncompressedSize);
8083
if (copyTo != null) {
81-
copyTo.write(buffer);
84+
copyTo.write(buf);
8285
}
83-
return limit = buffer.length;
86+
return limit = uncompressedSize;
8487
}
8588

8689
public Lz4InputStream(InputStream stream) {
@@ -93,6 +96,8 @@ public Lz4InputStream(ClickHouseFile file, InputStream stream, Runnable postClos
9396
this.decompressor = factory.fastDecompressor();
9497
this.stream = ClickHouseChecker.nonNull(stream, "InputStream");
9598
this.header = new byte[HEADER_LENGTH];
99+
100+
this.compressedBlock = ClickHouseByteBuffer.EMPTY_BYTES;
96101
}
97102

98103
@Override

Diff for: clickhouse-client/src/main/java/com/clickhouse/client/stream/Lz4OutputStream.java

+10-9
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,23 @@ public class Lz4OutputStream extends AbstractByteArrayOutputStream {
2121

2222
@Override
2323
protected void flushBuffer() throws IOException {
24-
int compressed = compressor.compress(buffer, 0, position, compressedBlock, 25);
24+
byte[] block = compressedBlock;
25+
block[16] = Lz4InputStream.MAGIC;
26+
int compressed = compressor.compress(buffer, 0, position, block, 25);
2527
int compressedSizeWithHeader = compressed + 9;
26-
BinaryStreamUtils.setInt32(compressedBlock, 17, compressedSizeWithHeader); // compressed size with header
27-
BinaryStreamUtils.setInt32(compressedBlock, 21, position); // uncompressed size
28-
long[] hash = ClickHouseCityHash.cityHash128(compressedBlock, 16, compressedSizeWithHeader);
29-
BinaryStreamUtils.setInt64(compressedBlock, 0, hash[0]);
30-
BinaryStreamUtils.setInt64(compressedBlock, 8, hash[1]);
31-
output.write(compressedBlock, 0, compressed + 25);
28+
BinaryStreamUtils.setInt32(block, 17, compressedSizeWithHeader); // compressed size with header
29+
BinaryStreamUtils.setInt32(block, 21, position); // uncompressed size
30+
long[] hash = ClickHouseCityHash.cityHash128(block, 16, compressedSizeWithHeader);
31+
BinaryStreamUtils.setInt64(block, 0, hash[0]);
32+
BinaryStreamUtils.setInt64(block, 8, hash[1]);
33+
output.write(block, 0, compressed + 25);
3234
position = 0;
3335
}
3436

3537
@Override
3638
protected void flushBuffer(byte[] bytes, int offset, int length) throws IOException {
3739
int maxLen = compressor.maxCompressedLength(length) + 15;
38-
byte[] block = maxLen < compressedBlock.length ? compressedBlock : new byte[maxLen];
40+
byte[] block = maxLen <= compressedBlock.length ? compressedBlock : new byte[maxLen];
3941
block[16] = Lz4InputStream.MAGIC;
4042

4143
int compressed = compressor.compress(bytes, offset, length, block, 25);
@@ -61,7 +63,6 @@ public Lz4OutputStream(ClickHouseFile file, OutputStream stream, int maxCompress
6163
compressor = factory.fastCompressor();
6264
// reserve the first 9 bytes for calculating checksum
6365
compressedBlock = new byte[compressor.maxCompressedLength(maxCompressBlockSize) + 15];
64-
compressedBlock[16] = Lz4InputStream.MAGIC;
6566
}
6667

6768
@Override

Diff for: clickhouse-client/src/test/java/com/clickhouse/client/ClientIntegrationTest.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,24 @@ public void testCompression(ClickHouseFormat format, ClickHouseBufferingMode buf
208208
boolean compressRequest, boolean compressResponse) throws ClickHouseException {
209209
ClickHouseNode server = getServer();
210210
String uuid = UUID.randomUUID().toString();
211+
ClickHouseClient.send(server, "create table if not exists test_compress_decompress(id UUID)engine=Memory");
211212
try (ClickHouseClient client = getClient()) {
212213
ClickHouseRequest<?> request = client.connect(server)
213214
.format(format)
214215
.option(ClickHouseClientOption.RESPONSE_BUFFERING, bufferingMode)
215216
.compressServerResponse(compressResponse)
216217
.decompressClientRequest(compressRequest);
218+
// start with insert
219+
try (ClickHouseResponse resp = request
220+
.query("insert into test_compress_decompress values(:uuid)").params(ClickHouseStringValue.of(uuid))
221+
.executeAndWait()) {
222+
Assert.assertNotNull(resp);
223+
}
224+
217225
boolean hasResult = false;
218226
try (ClickHouseResponse resp = request
219-
.query("select :uuid").params(ClickHouseStringValue.of(uuid)).executeAndWait()) {
227+
.query("select id from test_compress_decompress where id = :uuid")
228+
.params(ClickHouseStringValue.of(uuid)).executeAndWait()) {
220229
Assert.assertEquals(resp.firstRecord().getValue(0).asString(), uuid);
221230
hasResult = true;
222231
}

0 commit comments

Comments
 (0)