Add LZ4 compressor

- provides significant performance improvement for saving (37% in testing)
- at the cost of double the storage size (in testing)
This commit is contained in:
mcrcortex
2025-01-31 01:50:28 +10:00
parent a0132b8c67
commit ec67222855
4 changed files with 68 additions and 0 deletions

View File

@@ -199,6 +199,8 @@ dependencies {
include(implementation 'redis.clients:jedis:5.1.0') include(implementation 'redis.clients:jedis:5.1.0')
include(implementation('org.rocksdb:rocksdbjni:8.10.0')) include(implementation('org.rocksdb:rocksdbjni:8.10.0'))
include(implementation 'org.apache.commons:commons-pool2:2.12.0') include(implementation 'org.apache.commons:commons-pool2:2.12.0')
//include(implementation 'org.tukaani:xz:1.10')
include(implementation 'org.lz4:lz4-java:1.8.0')
//implementation 'org.rocksdb:rocksdbjni:8.10.0' //implementation 'org.rocksdb:rocksdbjni:8.10.0'
//implementation 'redis.clients:jedis:5.1.0' //implementation 'redis.clients:jedis:5.1.0'
} }

View File

@@ -0,0 +1,57 @@
package me.cortex.voxy.common.storage.compressors;
import me.cortex.voxy.common.storage.StorageCompressor;
import me.cortex.voxy.common.storage.config.CompressorConfig;
import me.cortex.voxy.common.storage.config.ConfigBuildCtx;
import me.cortex.voxy.common.util.MemoryBuffer;
import me.cortex.voxy.common.util.Pair;
import me.cortex.voxy.common.util.ThreadLocalMemoryBuffer;
import me.cortex.voxy.common.util.UnsafeUtil;
import me.cortex.voxy.common.world.SaveLoadSystem;
import net.jpountz.lz4.LZ4Factory;
import org.lwjgl.system.MemoryUtil;
import org.tukaani.xz.*;
import java.io.IOException;
public class LZ4Compressor implements StorageCompressor {
private static final ThreadLocalMemoryBuffer SCRATCH = new ThreadLocalMemoryBuffer(SaveLoadSystem.BIGGEST_SERIALIZED_SECTION_SIZE + 1024);
private final net.jpountz.lz4.LZ4Compressor compressor;
private final net.jpountz.lz4.LZ4FastDecompressor decompressor;
public LZ4Compressor() {
this.decompressor = LZ4Factory.nativeInstance().fastDecompressor();
this.compressor = LZ4Factory.nativeInstance().fastCompressor();
}
@Override
public MemoryBuffer compress(MemoryBuffer saveData) {
var res = new MemoryBuffer(this.compressor.maxCompressedLength((int) saveData.size)+4);
MemoryUtil.memPutInt(res.address, (int) saveData.size);
int size = this.compressor.compress(saveData.asByteBuffer(), 0, (int) saveData.size, res.asByteBuffer(), 4, (int) res.size-4);
return res.subSize(size+4);
}
@Override
public MemoryBuffer decompress(MemoryBuffer saveData) {
var res = SCRATCH.get().createUntrackedUnfreeableReference();
int size = this.decompressor.decompress(saveData.asByteBuffer(), 4, res.asByteBuffer(), 0, MemoryUtil.memGetInt(saveData.address));
return res.subSize(size);
}
@Override
public void close() {
}
public static class Config extends CompressorConfig {
@Override
public StorageCompressor build(ConfigBuildCtx ctx) {
return new LZ4Compressor();
}
public static String getConfigTypeName() {
return "LZ4";
}
}
}

View File

@@ -2,6 +2,7 @@ package me.cortex.voxy.common.util;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@@ -77,6 +78,9 @@ public class MemoryBuffer extends TrackedObject {
return new MemoryBuffer(this.tracked, this.address, size, this.freeable); return new MemoryBuffer(this.tracked, this.address, size, this.freeable);
} }
public ByteBuffer asByteBuffer() {
return MemoryUtil.memByteBuffer(this.address, (int) this.size);
}
//TODO: create like Long(offset) -> value at offset //TODO: create like Long(offset) -> value at offset
// methods for get and set, that way can have a single unifed system to ensure memory access bounds // methods for get and set, that way can have a single unifed system to ensure memory access bounds
@@ -100,4 +104,5 @@ public class MemoryBuffer extends TrackedObject {
public MemoryBuffer createUntrackedUnfreeableReference() { public MemoryBuffer createUntrackedUnfreeableReference() {
return new MemoryBuffer(false, this.address, this.size, false); return new MemoryBuffer(false, this.address, this.size, false);
} }
} }

View File

@@ -28,6 +28,10 @@ public class UnsafeUtil {
UNSAFE.copyMemory(null, src, dst, BYTE_ARRAY_BASE_OFFSET, dst.length); UNSAFE.copyMemory(null, src, dst, BYTE_ARRAY_BASE_OFFSET, dst.length);
} }
public static void memcpy(long src, int length, byte[] dst) {
UNSAFE.copyMemory(null, src, dst, BYTE_ARRAY_BASE_OFFSET, length);
}
//Copy the entire length of src to the dst memory where src is a byte array (source length from src) //Copy the entire length of src to the dst memory where src is a byte array (source length from src)
public static void memcpy(byte[] src, long dst) { public static void memcpy(byte[] src, long dst) {
UNSAFE.copyMemory(src, BYTE_ARRAY_BASE_OFFSET, null, dst, src.length); UNSAFE.copyMemory(src, BYTE_ARRAY_BASE_OFFSET, null, dst, src.length);