libdeflate is significantly faster than vanilla zlib, zlib-ng, and Cloudflare zlib. It is also MIT-licensed (so no licensing concerns). In addition, it simplifies a lot of the native code (something that's been tricky to get right). While we're at it, I have also taken the time to fine-time compression in Velocity in general. Thanks to this work, native compression only requires one JNI call, an improvement from the more than 2 (sometimes up to 5) that were possible before. This optimization also extends to the existing Java compressors, though they require potentially two JNI calls.
57 lines
1.8 KiB
C
57 lines
1.8 KiB
C
#include <assert.h>
|
|
#include <jni.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <libdeflate.h>
|
|
#include "jni_util.h"
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
Java_com_velocitypowered_natives_compression_NativeZlibInflate_init(JNIEnv *env,
|
|
jobject obj)
|
|
{
|
|
struct libdeflate_decompressor *decompress = libdeflate_alloc_decompressor();
|
|
if (decompress == NULL) {
|
|
// Out of memory!
|
|
throwException(env, "java/lang/OutOfMemoryError", "libdeflate allocate decompressor");
|
|
return 0;
|
|
}
|
|
|
|
return (jlong) decompress;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_com_velocitypowered_natives_compression_NativeZlibInflate_free(JNIEnv *env,
|
|
jobject obj,
|
|
jlong ctx)
|
|
{
|
|
libdeflate_free_decompressor((struct libdeflate_decompressor *) ctx);
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL
|
|
Java_com_velocitypowered_natives_compression_NativeZlibInflate_process(JNIEnv *env,
|
|
jobject obj,
|
|
jlong ctx,
|
|
jlong sourceAddress,
|
|
jint sourceLength,
|
|
jlong destinationAddress,
|
|
jint destinationLength,
|
|
jlong maximumSize)
|
|
{
|
|
struct libdeflate_decompressor *decompress = (struct libdeflate_decompressor *) ctx;
|
|
enum libdeflate_result result = libdeflate_zlib_decompress(decompress, (void *) sourceAddress,
|
|
sourceLength, (void *) destinationAddress, destinationLength, NULL);
|
|
|
|
switch (result) {
|
|
case LIBDEFLATE_SUCCESS:
|
|
// We are happy
|
|
return JNI_TRUE;
|
|
case LIBDEFLATE_BAD_DATA:
|
|
throwException(env, "java/util/zip/DataFormatException", "inflate data is bad");
|
|
return JNI_FALSE;
|
|
case LIBDEFLATE_SHORT_OUTPUT:
|
|
case LIBDEFLATE_INSUFFICIENT_SPACE:
|
|
// These cases are the same for us. We expect the full uncompressed size to be known.
|
|
throwException(env, "java/util/zip/DataFormatException", "uncompressed size is inaccurate");
|
|
return JNI_FALSE;
|
|
}
|
|
} |