diff --git a/kflate/src/commonMain/kotlin/com/rafambn/kflate/algorithm/DeflateCost.kt b/kflate/src/commonMain/kotlin/com/rafambn/kflate/algorithm/DeflateCost.kt index 5a59a15..0a45747 100644 --- a/kflate/src/commonMain/kotlin/com/rafambn/kflate/algorithm/DeflateCost.kt +++ b/kflate/src/commonMain/kotlin/com/rafambn/kflate/algorithm/DeflateCost.kt @@ -6,6 +6,10 @@ import com.rafambn.kflate.huffman.FIXED_DISTANCE_TREE import com.rafambn.kflate.huffman.FIXED_LENGTH_EXTRA_BITS import com.rafambn.kflate.huffman.FIXED_LENGTH_REVERSE_LOOKUP import com.rafambn.kflate.huffman.FIXED_LENGTH_TREE +import com.rafambn.kflate.huffman.buildHuffmanTreeFromFrequencies +import com.rafambn.kflate.huffman.calculateCodeLength +import com.rafambn.kflate.huffman.generateLengthCodes +import com.rafambn.kflate.util.countCodeLengthCodes internal fun chooseCostAwarePath( data: ByteArray, @@ -15,13 +19,150 @@ internal fun chooseCostAwarePath( costs: IntArray, choices: IntArray, ) { - // Fixed-tree widths provide stable prices before token frequencies can define a dynamic tree. + chooseCostAwarePath( + data = data, + start = start, + end = end, + matches = matches, + costs = costs, + choices = choices, + literalCosts = FIXED_LITERAL_COSTS, + lengthCosts = FIXED_LENGTH_COSTS, + distanceCosts = FIXED_DISTANCE_COSTS, + ) + + val size = end - start + if (size < COST_AWARE_DYNAMIC_MIN_WINDOW) return + + val initialChoices = choices.copyOf() + val initialCosts = costs.copyOf() + val initialLiteralFrequencies = IntArray(288) + val initialDistanceFrequencies = IntArray(32) + collectPathFrequencies( + data = data, + start = start, + matches = matches, + choices = initialChoices, + size = size, + literalFrequencies = initialLiteralFrequencies, + distanceFrequencies = initialDistanceFrequencies, + ) + + val initialDynamicTrees = buildDynamicTrees( + initialLiteralFrequencies, + initialDistanceFrequencies, + ) + val initialDynamicCosts = dynamicTokenCosts( + initialDynamicTrees.first, + initialDynamicTrees.second, + ) + val initialFixedCost = calculatePathCost( + data = data, + start = start, + matches = matches, + choices = initialChoices, + size = size, + literalCosts = FIXED_LITERAL_COSTS, + lengthCosts = FIXED_LENGTH_COSTS, + distanceCosts = FIXED_DISTANCE_COSTS, + ) + val initialDynamicCost = calculateDynamicPathCost( + data = data, + start = start, + matches = matches, + choices = initialChoices, + size = size, + literalCosts = initialDynamicCosts.first, + lengthCosts = initialDynamicCosts.second, + distanceCosts = initialDynamicCosts.third, + literalTree = initialDynamicTrees.first, + distanceTree = initialDynamicTrees.second, + ) + + // Skip refinement when this window estimate favors fixed coding. + if (initialDynamicCost >= initialFixedCost) return + + chooseCostAwarePath( + data = data, + start = start, + end = end, + matches = matches, + costs = costs, + choices = choices, + literalCosts = initialDynamicCosts.first, + lengthCosts = initialDynamicCosts.second, + distanceCosts = initialDynamicCosts.third, + ) + + val refinedChoices = choices.copyOf() + val refinedLiteralFrequencies = IntArray(288) + val refinedDistanceFrequencies = IntArray(32) + collectPathFrequencies( + data = data, + start = start, + matches = matches, + choices = refinedChoices, + size = size, + literalFrequencies = refinedLiteralFrequencies, + distanceFrequencies = refinedDistanceFrequencies, + ) + + val refinedDynamicTrees = buildDynamicTrees( + refinedLiteralFrequencies, + refinedDistanceFrequencies, + ) + val refinedDynamicCosts = dynamicTokenCosts( + refinedDynamicTrees.first, + refinedDynamicTrees.second, + ) + val refinedFixedCost = calculatePathCost( + data = data, + start = start, + matches = matches, + choices = refinedChoices, + size = size, + literalCosts = FIXED_LITERAL_COSTS, + lengthCosts = FIXED_LENGTH_COSTS, + distanceCosts = FIXED_DISTANCE_COSTS, + ) + val refinedDynamicCost = calculateDynamicPathCost( + data = data, + start = start, + matches = matches, + choices = refinedChoices, + size = size, + literalCosts = refinedDynamicCosts.first, + lengthCosts = refinedDynamicCosts.second, + distanceCosts = refinedDynamicCosts.third, + literalTree = refinedDynamicTrees.first, + distanceTree = refinedDynamicTrees.second, + ) + + val initialEncodedCost = minOf(initialFixedCost, initialDynamicCost) + val refinedEncodedCost = minOf(refinedFixedCost, refinedDynamicCost) + if (refinedEncodedCost >= initialEncodedCost) { + initialChoices.copyInto(choices) + initialCosts.copyInto(costs) + } +} + +private fun chooseCostAwarePath( + data: ByteArray, + start: Int, + end: Int, + matches: IntArray, + costs: IntArray, + choices: IntArray, + literalCosts: IntArray, + lengthCosts: IntArray, + distanceCosts: IntArray, +) { val size = end - start costs[size] = 0 for (offset in size - 1 downTo 0) { val literal = data[start + offset].toInt() and 0xFF - var bestCost = fixedLiteralBitCost(literal) + costs[offset + 1] + var bestCost = literalCosts[literal] + costs[offset + 1] var bestLength = 1 val match = matches[offset] val distance = match and MATCH_DISTANCE_MASK @@ -30,16 +171,17 @@ internal fun chooseCostAwarePath( val searchedLength = minOf(containedLength, COST_AWARE_LENGTH_SEARCH) for (length in 3..searchedLength) { - val candidateCost = fixedMatchBitCost(length, distance) + costs[offset + length] + val candidateCost = matchBitCost(length, distance, lengthCosts, distanceCosts) + + costs[offset + length] if (candidateCost <= bestCost) { bestCost = candidateCost bestLength = length } } - if (maximumLength > searchedLength) { + if (maximumLength >= 3 && maximumLength > searchedLength) { val nextCost = if (offset + maximumLength <= size) costs[offset + maximumLength] else 0 - val candidateCost = fixedMatchBitCost(maximumLength, distance) + nextCost + val candidateCost = matchBitCost(maximumLength, distance, lengthCosts, distanceCosts) + nextCost if (candidateCost <= bestCost) { bestCost = candidateCost bestLength = maximumLength @@ -51,20 +193,187 @@ internal fun chooseCostAwarePath( } } +private fun collectPathFrequencies( + data: ByteArray, + start: Int, + matches: IntArray, + choices: IntArray, + size: Int, + literalFrequencies: IntArray, + distanceFrequencies: IntArray, +) { + var offset = 0 + while (offset < size) { + val length = choices[offset] + if (length == 1) { + literalFrequencies[data[start + offset].toInt() and 0xFF]++ + } else { + val match = matches[offset] + val distance = match and MATCH_DISTANCE_MASK + val lengthSymbol = FIXED_LENGTH_REVERSE_LOOKUP[length] and 31 + val distanceSymbol = FIXED_DISTANCE_REVERSE_LOOKUP[distance] and 31 + literalFrequencies[257 + lengthSymbol]++ + distanceFrequencies[distanceSymbol]++ + } + offset += length + } + + literalFrequencies[256]++ + if (distanceFrequencies.all { it == 0 }) { + distanceFrequencies[0] = 1 + } +} + +private fun buildDynamicTrees( + literalFrequencies: IntArray, + distanceFrequencies: IntArray, +): Pair { + return Pair( + buildHuffmanTreeFromFrequencies(literalFrequencies, 15).tree, + buildHuffmanTreeFromFrequencies(distanceFrequencies, 15).tree, + ) +} + +private fun dynamicTokenCosts( + literalTree: ByteArray, + distanceTree: ByteArray, +): Triple { + val literalCosts = IntArray(288) + for (symbol in literalCosts.indices) { + val dynamicCost = literalTree.getOrNull(symbol)?.toInt()?.and(0xFF) ?: 0 + literalCosts[symbol] = if (dynamicCost > 0) dynamicCost else FIXED_LITERAL_COSTS[symbol] + } + + val lengthCosts = IntArray(31) + for (symbol in lengthCosts.indices) { + val dynamicCost = literalTree.getOrNull(257 + symbol)?.toInt()?.and(0xFF) ?: 0 + lengthCosts[symbol] = if (dynamicCost > 0) { + dynamicCost + (FIXED_LENGTH_EXTRA_BITS[symbol].toInt() and 0xFF) + } else { + FIXED_LENGTH_COSTS[symbol] + } + } + + val distanceCosts = IntArray(31) + for (symbol in distanceCosts.indices) { + val dynamicCost = distanceTree.getOrNull(symbol)?.toInt()?.and(0xFF) ?: 0 + distanceCosts[symbol] = if (dynamicCost > 0) { + dynamicCost + (FIXED_DISTANCE_EXTRA_BITS[symbol].toInt() and 0xFF) + } else { + FIXED_DISTANCE_COSTS[symbol] + } + } + + return Triple(literalCosts, lengthCosts, distanceCosts) +} + +private fun calculatePathCost( + data: ByteArray, + start: Int, + matches: IntArray, + choices: IntArray, + size: Int, + literalCosts: IntArray, + lengthCosts: IntArray, + distanceCosts: IntArray, +): Int { + var cost = literalCosts[256] + var offset = 0 + while (offset < size) { + val length = choices[offset] + if (length == 1) { + cost += literalCosts[data[start + offset].toInt() and 0xFF] + } else { + val match = matches[offset] + cost += matchBitCost( + length, + match and MATCH_DISTANCE_MASK, + lengthCosts, + distanceCosts, + ) + } + offset += length + } + return cost +} + +private fun calculateDynamicPathCost( + data: ByteArray, + start: Int, + matches: IntArray, + choices: IntArray, + size: Int, + literalCosts: IntArray, + lengthCosts: IntArray, + distanceCosts: IntArray, + literalTree: ByteArray, + distanceTree: ByteArray, +): Int { + val tokenCost = calculatePathCost( + data = data, + start = start, + matches = matches, + choices = choices, + size = size, + literalCosts = literalCosts, + lengthCosts = lengthCosts, + distanceCosts = distanceCosts, + ) + val (literalCodeLengths, _) = generateLengthCodes(literalTree) + val (distanceCodeLengths, _) = generateLengthCodes(distanceTree) + val codeLengthFrequencies = IntArray(19) + for (code in literalCodeLengths) { + codeLengthFrequencies[code.toInt() and 31]++ + } + for (code in distanceCodeLengths) { + codeLengthFrequencies[code.toInt() and 31]++ + } + + val codeLengthTree = buildHuffmanTreeFromFrequencies(codeLengthFrequencies, 7).tree + val numCodeLengthCodes = countCodeLengthCodes(codeLengthTree) + val headerCost = 14 + 3 * numCodeLengthCodes + + calculateCodeLength(codeLengthFrequencies, codeLengthTree) + + 2 * codeLengthFrequencies[16] + + 3 * codeLengthFrequencies[17] + + 7 * codeLengthFrequencies[18] + return tokenCost + headerCost +} + +private fun matchBitCost( + length: Int, + distance: Int, + lengthCosts: IntArray, + distanceCosts: IntArray, +): Int { + val lengthSymbol = FIXED_LENGTH_REVERSE_LOOKUP[length] and 31 + val distanceSymbol = FIXED_DISTANCE_REVERSE_LOOKUP[distance] and 31 + return lengthCosts[lengthSymbol] + distanceCosts[distanceSymbol] +} + internal fun fixedLiteralBitCost(literal: Int): Int { return FIXED_LENGTH_TREE[literal].toInt() and 0xFF } internal fun fixedMatchBitCost(length: Int, distance: Int): Int { - val lengthSymbol = FIXED_LENGTH_REVERSE_LOOKUP[length] and 31 - val distanceSymbol = FIXED_DISTANCE_REVERSE_LOOKUP[distance] and 31 - return (FIXED_LENGTH_TREE[257 + lengthSymbol].toInt() and 0xFF) + - (FIXED_LENGTH_EXTRA_BITS[lengthSymbol].toInt() and 0xFF) + - (FIXED_DISTANCE_TREE[distanceSymbol].toInt() and 0xFF) + - (FIXED_DISTANCE_EXTRA_BITS[distanceSymbol].toInt() and 0xFF) + return matchBitCost(length, distance, FIXED_LENGTH_COSTS, FIXED_DISTANCE_COSTS) } // Bound memory without forcing matches to stop at a window boundary. internal const val COST_AWARE_WINDOW_SIZE = 262_144 +private const val COST_AWARE_DYNAMIC_MIN_WINDOW = 1_024 // Price every short match length plus the longest available match. private const val COST_AWARE_LENGTH_SEARCH = 64 + +private val FIXED_LITERAL_COSTS = IntArray(288) { + FIXED_LENGTH_TREE[it].toInt() and 0xFF +} + +private val FIXED_LENGTH_COSTS = IntArray(31) { symbol -> + (FIXED_LENGTH_TREE[257 + symbol].toInt() and 0xFF) + + (FIXED_LENGTH_EXTRA_BITS[symbol].toInt() and 0xFF) +} + +private val FIXED_DISTANCE_COSTS = IntArray(31) { symbol -> + (FIXED_DISTANCE_TREE[symbol].toInt() and 0xFF) + + (FIXED_DISTANCE_EXTRA_BITS[symbol].toInt() and 0xFF) +} diff --git a/kflate/src/commonMain/kotlin/com/rafambn/kflate/huffman/HuffmanCode.kt b/kflate/src/commonMain/kotlin/com/rafambn/kflate/huffman/HuffmanCode.kt index 427985e..64f3d70 100644 --- a/kflate/src/commonMain/kotlin/com/rafambn/kflate/huffman/HuffmanCode.kt +++ b/kflate/src/commonMain/kotlin/com/rafambn/kflate/huffman/HuffmanCode.kt @@ -148,7 +148,7 @@ internal fun buildHuffmanTreeFromFrequencies(frequencies: IntArray, maxBits: Int nodes.sortBy { it.frequency } val combinedNodes = ArrayList(nodes) - combinedNodes.add(HuffmanNode(symbol = -1, frequency = 25001)) + combinedNodes.add(HuffmanNode(symbol = -1, frequency = Int.MAX_VALUE)) var lowFreqIndex = 0 var highFreqIndex = 1 diff --git a/kflate/src/jvmTest/kotlin/AlgorithmCoverageTest.kt b/kflate/src/jvmTest/kotlin/AlgorithmCoverageTest.kt index 8937532..7171e89 100644 --- a/kflate/src/jvmTest/kotlin/AlgorithmCoverageTest.kt +++ b/kflate/src/jvmTest/kotlin/AlgorithmCoverageTest.kt @@ -272,6 +272,44 @@ class AlgorithmCoverageTest { assertEquals(4, choices[1]) } + @Test + fun costAwareParsingRepricesRareMatchesWithDynamicTrees() { + val data = ByteArray(2_048) + for (symbol in 1..255) { + data[symbol + 2] = symbol.toByte() + } + val matches = IntArray(data.size) + matches[0] = (3 shl MATCH_DISTANCE_BITS) or 1 + val costs = IntArray(data.size + 1) + val choices = IntArray(data.size) + + chooseCostAwarePath(data, 0, data.size, matches, costs, choices) + + assertEquals(1, choices[0]) + } + + @Test + fun costAwareParsingRejectsPackedTwoByteNoMatchAtWindowEnd() { + val data = ByteArray(2_048) + val matches = IntArray(data.size) + var literalSymbol = 0 + for (offset in 0 until data.size - 1) { + if (offset % 3 == 0 && offset + 3 <= data.size) { + matches[offset] = (3 shl MATCH_DISTANCE_BITS) or 1 + } else { + data[offset] = (if (literalSymbol < 255) literalSymbol++ else 0).toByte() + } + } + data[data.lastIndex] = 255.toByte() + matches[data.lastIndex] = 2 shl MATCH_DISTANCE_BITS + + val costs = IntArray(data.size + 1) + val choices = IntArray(data.size) + chooseCostAwarePath(data, 0, data.size, matches, costs, choices) + + assertEquals(1, choices[data.lastIndex]) + } + @Test fun costAwareLevelRoundTripsWindowsAndDictionaries() { val multipleWindows = ByteArray(COST_AWARE_WINDOW_SIZE * 2 + 3) @@ -304,6 +342,10 @@ class AlgorithmCoverageTest { assertEquals(0, buildHuffmanTreeFromFrequencies(IntArray(4), 3).maxBits) assertEquals(1, buildHuffmanTreeFromFrequencies(intArrayOf(0, 7), 3).maxBits) + val highFrequencyTree = buildHuffmanTreeFromFrequencies(IntArray(4) { 30_000 }, 15) + assertEquals(2, highFrequencyTree.maxBits) + assertTrue(highFrequencyTree.tree.all { it.toInt() == 2 }) + val limited = buildHuffmanTreeFromFrequencies( intArrayOf(1, 1, 2, 3, 5, 8, 13, 21), 3, diff --git a/performance/2026-09-09-dynamic/RESULTS.md b/performance/2026-09-09-dynamic/RESULTS.md new file mode 100644 index 0000000..def7b7e --- /dev/null +++ b/performance/2026-09-09-dynamic/RESULTS.md @@ -0,0 +1,79 @@ +# Refine level 9 parsing with dynamic Huffman prices + +Build Huffman prices from the fixed-cost parse, try one dynamic-cost refinement, and keep it only if the rebuilt full-window estimate improves. This adds parsing work and scratch allocations. The estimate spans a parser window, which may become multiple encoded blocks, so it does not guarantee against size regressions on arbitrary inputs. Reject candidates shorter than the DEFLATE minimum of three bytes, including the packed two-byte no-match sentinel at window boundaries. The Huffman builder sentinel becomes Int.MAX_VALUE because window frequencies can exceed 25001. + +Base: `fe2ff51`, `dev-1.1.0`. Measured on September 9, 2026 on Linux x86_64, Intel Core i7-11800H. JVM uses JBR 17.0.14; Node uses 22.22.1. + +Only KFlate was timed. Kompress sizes and timings come unchanged from the trusted September 8 archive in `performance/history.json`. Benchmark setup may produce Kompress streams for decoder validation outside timing. + +## Compressed size + +The JVM sweep compresses all seven tracked corpora at every listed level. Every output must round-trip through both the JDK RAW inflater and KFlate. Byte counts are deterministic. Single-run durations in the sweep JSON are diagnostic, not throughput benchmarks. + +Output reduction is `(beforeBytes - afterBytes) / beforeBytes`. Totals weight each corpus by its compressed bytes; they are not averages of percentage changes. + +| Level | Before bytes | After bytes | Output reduction | +| ---: | ---: | ---: | ---: | +| 0 | 76,379,868 | 76,379,868 | 0.0000% | +| 1 | 40,222,941 | 40,222,941 | 0.0000% | +| 2 | 39,269,936 | 39,269,936 | 0.0000% | +| 3 | 38,906,551 | 38,906,551 | 0.0000% | +| 4 | 38,333,169 | 38,333,169 | 0.0000% | +| 5 | 38,293,272 | 38,293,272 | 0.0000% | +| 6 | 37,882,044 | 37,882,044 | 0.0000% | +| 7 | 37,868,330 | 37,868,330 | 0.0000% | +| 8 | 37,737,043 | 37,737,043 | 0.0000% | +| 9 | 37,251,418 | 36,780,911 | 1.2631% | + +### Level 6 + +| Corpus | Before bytes | After bytes | Reduction | Saved JVM Kompress bytes | +| --- | ---: | ---: | ---: | ---: | +| simpleText | 84 | 84 | 0.0000% | 84 | +| text | 506,455 | 506,455 | 0.0000% | 505,318 | +| model3D | 2,153 | 2,153 | 0.0000% | 2,149 | +| Rainier.bmp | 3,283,450 | 3,283,450 | 0.0000% | 3,275,337 | +| Maltese.bmp | 7,158,472 | 7,158,472 | 0.0000% | 7,096,685 | +| Sunrise.bmp | 26,838,825 | 26,838,825 | 0.0000% | 26,698,992 | +| compressed_MVT.pbf | 92,605 | 92,605 | 0.0000% | 91,408 | + +### Level 9 + +| Corpus | Before bytes | After bytes | Reduction | Saved JVM Kompress bytes | +| --- | ---: | ---: | ---: | ---: | +| simpleText | 84 | 84 | 0.0000% | 84 | +| text | 492,523 | 488,094 | 0.8992% | 503,400 | +| model3D | 2,153 | 2,153 | 0.0000% | 2,149 | +| Rainier.bmp | 3,258,570 | 3,255,198 | 0.1035% | 3,270,382 | +| Maltese.bmp | 7,034,092 | 6,860,004 | 2.4749% | 7,090,887 | +| Sunrise.bmp | 26,372,269 | 26,083,978 | 1.0932% | 26,652,810 | +| compressed_MVT.pbf | 91,727 | 91,400 | 0.3565% | 91,400 | + +## Compression timing + +Development measurements use three one-second warmups and five one-second measurement iterations. JVM has one fresh fork per corpus; Native has one process per corpus; Wasm uses one runner. These shorter runs detect broad tradeoffs and are not release-grade speed claims. Raw samples, errors and confidence intervals are retained. No decompression speed claim is made. + +### jvm, level 9 + +| Corpus | Before ms | After ms | Before/after speedup | Saved Kompress/after speedup | +| --- | ---: | ---: | ---: | ---: | +| simpleText | 0.0272 | 0.0272 | 1.000x | 0.149x | +| text | 192.2328 | 233.2505 | 0.824x | 0.319x | +| model3D | 0.0969 | 0.1644 | 0.589x | 0.183x | +| Rainier.bmp | 2551.1684 | 2680.9962 | 0.952x | 0.041x | +| Maltese.bmp | 1206.9043 | 1650.6747 | 0.731x | 0.240x | +| Sunrise.bmp | 11385.8072 | 12729.0296 | 0.894x | 0.132x | +| compressed_MVT.pbf | 9.3247 | 11.5040 | 0.811x | 0.362x | + + +## Validation and reproduction + +Linux JVM tests and 100% instruction/branch coverage verification passed, including the packed two-byte boundary regression, multiple windows, dictionaries and high Huffman frequencies. All 70 corpus/level outputs passed JDK and KFlate decompression; levels 0 through 8 are unchanged and level 9 has no fixture size regressions. All seven level 9 JMH compression cases completed. The combined variant also passed all 70 cases after the minimum-length fix. No Native or Wasm timing claim is made for this standalone variant. + +Tracked source diff SHA-256: `9450056c9788829eb49cd6364321384fa4b483f912838ebe34855b1947e79591`. Added source/test files are present in this commit. + +Linux build: `ANDROID_HOME=/home/rafael/Android/Sdk ./gradlew :kflate:jvmTest :kflate:jvmBenchmarkBenchmarkJar --no-parallel --max-workers=1`. + +For level 9 timing, set `BENCHMARK_COMPRESSION_LEVEL` to 9 in `BenchmarkState.kt` before building; leave it at 6 otherwise. Use JBR 17.0.14 and the generated JMH jar with the main and benchmark classes on its classpath. Run `org.openjdk.jmh.Main` with the relevant `CompressionBenchmarks` method filter and `-wi 3 -i 5 -w 1s -r 1s -f 1 -foe true -rf json -rff result.json`. Only KFlate benchmark methods should be selected. + +Compile `RatioSweep.java` against the KFlate classes and generated benchmark jar, then run it with `kflate/src/jvmTest/resources FIRST_LEVEL LAST_LEVEL`. It checks both JDK and KFlate decompression and records deterministic sizes and output hashes. diff --git a/performance/2026-09-09-dynamic/RatioSweep.java b/performance/2026-09-09-dynamic/RatioSweep.java new file mode 100644 index 0000000..112ba7d --- /dev/null +++ b/performance/2026-09-09-dynamic/RatioSweep.java @@ -0,0 +1,42 @@ +import com.rafambn.kflate.KFlate; +import com.rafambn.kflate.compression.Raw; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.security.MessageDigest; +import java.util.HexFormat; +import java.util.zip.Inflater; + +public class RatioSweep { + public static void main(String[] args) throws Exception { + String[] names = {"simpleText", "text", "model3D", "Rainier.bmp", "Maltese.bmp", "Sunrise.bmp", "compressed_MVT.pbf"}; + int first = args.length > 1 ? Integer.parseInt(args[1]) : 0; + int last = args.length > 2 ? Integer.parseInt(args[2]) : 9; + for (String name : names) { + if (args.length > 3 && !name.equals(args[3])) continue; + byte[] input = Files.readAllBytes(Path.of(args[0], name)); + for (int level = first; level <= last; level++) { + long start = System.nanoTime(); + byte[] output = KFlate.INSTANCE.compress(input, new Raw(level, null)); + double ms = (System.nanoTime() - start) / 1e6; + Inflater inflater = new Inflater(true); + try { + inflater.setInput(output); + byte[] decoded = new byte[input.length + 1]; + int count = inflater.inflate(decoded); + if (!inflater.finished() || count != input.length || !Arrays.equals(input, Arrays.copyOf(decoded, count))) { + Files.write(Path.of("/tmp/kflate-invalid-" + name + "-" + level + ".deflate"), output); + int mismatch = Arrays.mismatch(input, Arrays.copyOf(decoded, count)); + throw new AssertionError("Invalid output: " + name + " level " + level + " decoded=" + count + " expected=" + input.length + " finished=" + inflater.finished() + " remaining=" + inflater.getRemaining() + " mismatch=" + mismatch); + } + } finally { + inflater.end(); + } + if (!Arrays.equals(input, KFlate.INSTANCE.decompress(output, new com.rafambn.kflate.decompression.Raw(null, null)))) { + throw new AssertionError("KFlate round trip: " + name + " level " + level); + } + System.out.printf(java.util.Locale.ROOT, "{\"corpus\":\"%s\",\"level\":%d,\"originalSizeBytes\":%d,\"compressedSizeBytes\":%d,\"singleRunMs\":%.6f,\"sha256\":\"%s\"}%n", name, level, input.length, output.length, ms, HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(output))); + } + } + } +} diff --git a/performance/2026-09-09-dynamic/after-jmh.json b/performance/2026-09-09-dynamic/after-jmh.json new file mode 100644 index 0000000..4fe58b8 --- /dev/null +++ b/performance/2026-09-09-dynamic/after-jmh.json @@ -0,0 +1,380 @@ +[ + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "simpleText" + }, + "primaryMetric" : { + "score" : 2.719795151933315E-5, + "scoreError" : 3.2049187120831877E-6, + "scoreConfidence" : [ + 2.3993032807249964E-5, + 3.0402870231416338E-5 + ], + "scorePercentiles" : { + "0.0" : 2.6562323435674067E-5, + "50.0" : 2.6616486694342435E-5, + "90.0" : 2.8164387632697886E-5, + "95.0" : 2.8164387632697886E-5, + "99.0" : 2.8164387632697886E-5, + "99.9" : 2.8164387632697886E-5, + "99.99" : 2.8164387632697886E-5, + "99.999" : 2.8164387632697886E-5, + "99.9999" : 2.8164387632697886E-5, + "100.0" : 2.8164387632697886E-5 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 2.8052458770404443E-5, + 2.8164387632697886E-5, + 2.659410106354693E-5, + 2.6616486694342435E-5, + 2.6562323435674067E-5 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "text" + }, + "primaryMetric" : { + "score" : 0.2332505178, + "scoreError" : 0.002148390153575744, + "scoreConfidence" : [ + 0.23110212764642427, + 0.23539890795357574 + ], + "scorePercentiles" : { + "0.0" : 0.2327619774, + "50.0" : 0.232953819, + "90.0" : 0.234003933, + "95.0" : 0.234003933, + "99.0" : 0.234003933, + "99.9" : 0.234003933, + "99.99" : 0.234003933, + "99.999" : 0.234003933, + "99.9999" : 0.234003933, + "100.0" : 0.234003933 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 0.232953819, + 0.234003933, + 0.2328479198, + 0.2327619774, + 0.2336849398 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "model3D" + }, + "primaryMetric" : { + "score" : 1.6436576357165678E-4, + "scoreError" : 1.2596113460375633E-5, + "scoreConfidence" : [ + 1.5176965011128114E-4, + 1.7696187703203242E-4 + ], + "scorePercentiles" : { + "0.0" : 1.5934799888481758E-4, + "50.0" : 1.6580862964190983E-4, + "90.0" : 1.669337710280374E-4, + "95.0" : 1.669337710280374E-4, + "99.0" : 1.669337710280374E-4, + "99.9" : 1.669337710280374E-4, + "99.99" : 1.669337710280374E-4, + "99.999" : 1.669337710280374E-4, + "99.9999" : 1.669337710280374E-4, + "100.0" : 1.669337710280374E-4 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 1.5934799888481758E-4, + 1.6281484453849911E-4, + 1.6692357376502003E-4, + 1.6580862964190983E-4, + 1.669337710280374E-4 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "Rainier.bmp" + }, + "primaryMetric" : { + "score" : 2.68099617, + "scoreError" : 0.7885563965332603, + "scoreConfidence" : [ + 1.8924397734667395, + 3.46955256653326 + ], + "scorePercentiles" : { + "0.0" : 2.506635972, + "50.0" : 2.585388356, + "90.0" : 2.903237219, + "95.0" : 2.903237219, + "99.0" : 2.903237219, + "99.9" : 2.903237219, + "99.99" : 2.903237219, + "99.999" : 2.903237219, + "99.9999" : 2.903237219, + "100.0" : 2.903237219 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 2.901933504, + 2.903237219, + 2.585388356, + 2.506635972, + 2.507785799 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "Maltese.bmp" + }, + "primaryMetric" : { + "score" : 1.650674704, + "scoreError" : 0.035071852261538056, + "scoreConfidence" : [ + 1.615602851738462, + 1.6857465562615381 + ], + "scorePercentiles" : { + "0.0" : 1.638377177, + "50.0" : 1.655827974, + "90.0" : 1.65843618, + "95.0" : 1.65843618, + "99.0" : 1.65843618, + "99.9" : 1.65843618, + "99.99" : 1.65843618, + "99.999" : 1.65843618, + "99.9999" : 1.65843618, + "100.0" : 1.65843618 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 1.657207507, + 1.65843618, + 1.655827974, + 1.638377177, + 1.643524682 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "Sunrise.bmp" + }, + "primaryMetric" : { + "score" : 12.7290295962, + "scoreError" : 0.5525624445182846, + "scoreConfidence" : [ + 12.176467151681715, + 13.281592040718285 + ], + "scorePercentiles" : { + "0.0" : 12.568172428, + "50.0" : 12.823767139, + "90.0" : 12.840710954, + "95.0" : 12.840710954, + "99.0" : 12.840710954, + "99.9" : 12.840710954, + "99.99" : 12.840710954, + "99.999" : 12.840710954, + "99.9999" : 12.840710954, + "100.0" : 12.840710954 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 12.840710954, + 12.836645489, + 12.823767139, + 12.568172428, + 12.575851971 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "compressed_MVT.pbf" + }, + "primaryMetric" : { + "score" : 0.011504001176764705, + "scoreError" : 0.0021709856642339186, + "scoreConfidence" : [ + 0.009333015512530787, + 0.013674986840998623 + ], + "scorePercentiles" : { + "0.0" : 0.010519714291666666, + "50.0" : 0.011782424517647059, + "90.0" : 0.011846557505882352, + "95.0" : 0.011846557505882352, + "99.0" : 0.011846557505882352, + "99.9" : 0.011846557505882352, + "99.99" : 0.011846557505882352, + "99.999" : 0.011846557505882352, + "99.9999" : 0.011846557505882352, + "100.0" : 0.011846557505882352 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 0.011846557505882352, + 0.011782424517647059, + 0.011830209235294117, + 0.011541100333333333, + 0.010519714291666666 + ] + ] + }, + "secondaryMetrics" : { + } + } +] diff --git a/performance/2026-09-09-dynamic/after-sizes.jsonl b/performance/2026-09-09-dynamic/after-sizes.jsonl new file mode 100644 index 0000000..0967815 --- /dev/null +++ b/performance/2026-09-09-dynamic/after-sizes.jsonl @@ -0,0 +1,70 @@ +{"corpus":"simpleText","level":0,"originalSizeBytes":100,"compressedSizeBytes":105,"singleRunMs":20.420716,"sha256":"7a4f86cab2c64d7a755ba6244b34b85122a3d7e629073b34930b3d477585100b"} +{"corpus":"simpleText","level":1,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":11.751386,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":2,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.347467,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":3,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.315407,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":4,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.401460,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":5,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.358148,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":6,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.261222,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":7,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.262076,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":8,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.275697,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"simpleText","level":9,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.680594,"sha256":"dfc6c55d533c49b70bb5f358f19c146ad3443a985e6f76144b1ee4e16286e499"} +{"corpus":"text","level":0,"originalSizeBytes":1232923,"compressedSizeBytes":1233018,"singleRunMs":4.814965,"sha256":"cfab8f8c4f21f3b8b8b3cd60a85b7e1243a5aad2a06fa863e9eec73187488605"} +{"corpus":"text","level":1,"originalSizeBytes":1232923,"compressedSizeBytes":599813,"singleRunMs":60.766331,"sha256":"143d81705ac095d278fb6e1fa3932a500916369bc4596da6885cfe2e7d81f756"} +{"corpus":"text","level":2,"originalSizeBytes":1232923,"compressedSizeBytes":581519,"singleRunMs":37.870431,"sha256":"611557ab65d0c35387dfc6121636fd006ff3a237c3a838835f67e31cc79983ce"} +{"corpus":"text","level":3,"originalSizeBytes":1232923,"compressedSizeBytes":565252,"singleRunMs":37.864573,"sha256":"19a3c8ae4b1f0ed21ed27b0e0bb87c22d0ebf7259406f8d748c3d79c3d4888ee"} +{"corpus":"text","level":4,"originalSizeBytes":1232923,"compressedSizeBytes":531466,"singleRunMs":56.182404,"sha256":"d27df2bc4d16b3c9b193b68a7c72cc4208ed4505c2eaafbfc078fbfb29bdd3e1"} +{"corpus":"text","level":5,"originalSizeBytes":1232923,"compressedSizeBytes":521837,"singleRunMs":67.778662,"sha256":"49036c7d2710a45efdf31f3cb63b002ecffe3f8732566b65cd54997e02788bbd"} +{"corpus":"text","level":6,"originalSizeBytes":1232923,"compressedSizeBytes":506455,"singleRunMs":78.658040,"sha256":"3ba0571fcc563672f279cad303810e537dfc18ce61680207dfcd3e2e91abaf67"} +{"corpus":"text","level":7,"originalSizeBytes":1232923,"compressedSizeBytes":506097,"singleRunMs":78.711318,"sha256":"f7b312a37b78362b74cb5c5b1da94aaadec93a4629b19fc3d5cf5300498b993d"} +{"corpus":"text","level":8,"originalSizeBytes":1232923,"compressedSizeBytes":513489,"singleRunMs":83.362418,"sha256":"0008d4cc1d35364514f380a591ec7c01edc292742c5654a50795008ae3b6989c"} +{"corpus":"text","level":9,"originalSizeBytes":1232923,"compressedSizeBytes":488094,"singleRunMs":264.814823,"sha256":"39f6f3af429bf689a09a37bb94a1ac4ea5d368251814af5ce5ae54c9e09e8f2f"} +{"corpus":"model3D","level":0,"originalSizeBytes":2478,"compressedSizeBytes":2483,"singleRunMs":0.058049,"sha256":"7d1354e385451c35f23c9be4ce28245d554943a2219ff0cf3481d5c0a02a4919"} +{"corpus":"model3D","level":1,"originalSizeBytes":2478,"compressedSizeBytes":2169,"singleRunMs":0.198789,"sha256":"cc762b082d3527b26e531d8f8cd04e17467595b5ef1ea32a541b275663e3ef96"} +{"corpus":"model3D","level":2,"originalSizeBytes":2478,"compressedSizeBytes":2168,"singleRunMs":0.153188,"sha256":"7be0094d5c194b33c4337a5c971d25c3ed4e2c3d1d195a75225130310d911733"} +{"corpus":"model3D","level":3,"originalSizeBytes":2478,"compressedSizeBytes":2166,"singleRunMs":0.149645,"sha256":"fa0c3d7374a90b6f9d7f14095e59ecd375b976cd57423d40e18d26332bf768c6"} +{"corpus":"model3D","level":4,"originalSizeBytes":2478,"compressedSizeBytes":2165,"singleRunMs":0.162433,"sha256":"b8bb6e5b0de2dac94d69e676871bd5538d16c6fc909b4a926a9fb42ca33d4846"} +{"corpus":"model3D","level":5,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.162788,"sha256":"4b0cd916546275b9ae57fab7c6d88d94ed1e669669b30c158eb4c06e85e8f0ad"} +{"corpus":"model3D","level":6,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.189867,"sha256":"4b0cd916546275b9ae57fab7c6d88d94ed1e669669b30c158eb4c06e85e8f0ad"} +{"corpus":"model3D","level":7,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.197933,"sha256":"4b0cd916546275b9ae57fab7c6d88d94ed1e669669b30c158eb4c06e85e8f0ad"} +{"corpus":"model3D","level":8,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.121352,"sha256":"4b0cd916546275b9ae57fab7c6d88d94ed1e669669b30c158eb4c06e85e8f0ad"} +{"corpus":"model3D","level":9,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.523221,"sha256":"450f6437d13a19585d0df05da961baf30023451a17612fd84a683a2f2f450ea7"} +{"corpus":"Rainier.bmp","level":0,"originalSizeBytes":6220854,"compressedSizeBytes":6221329,"singleRunMs":4.506621,"sha256":"acf3201e43c503d2705565195eb3bfc176e674b00bc8eeaf55411409398ffb7e"} +{"corpus":"Rainier.bmp","level":1,"originalSizeBytes":6220854,"compressedSizeBytes":3387685,"singleRunMs":128.510272,"sha256":"d86acee038a3272ef53f6be323c941d63ee7fc64544d489d3e81061ba2cb4296"} +{"corpus":"Rainier.bmp","level":2,"originalSizeBytes":6220854,"compressedSizeBytes":3357387,"singleRunMs":113.135627,"sha256":"cb08babeb442d0a7b5ef341c5114d36a9a40c0e9640c848accd37d151af8a3a6"} +{"corpus":"Rainier.bmp","level":3,"originalSizeBytes":6220854,"compressedSizeBytes":3345679,"singleRunMs":108.262991,"sha256":"3c62f22018cd809c25f3c70a9672872a0a0ec916ad89b7eca944c0415093b7dd"} +{"corpus":"Rainier.bmp","level":4,"originalSizeBytes":6220854,"compressedSizeBytes":3325593,"singleRunMs":104.033492,"sha256":"84cf1da1aa0fd2007e5de90ff81e779e616020cf3548affd456350296f12ce6c"} +{"corpus":"Rainier.bmp","level":5,"originalSizeBytes":6220854,"compressedSizeBytes":3313388,"singleRunMs":110.900404,"sha256":"54a7d786396e86dae90937df6dd8425d69557991ec611265a212ad85037e2b63"} +{"corpus":"Rainier.bmp","level":6,"originalSizeBytes":6220854,"compressedSizeBytes":3283450,"singleRunMs":123.108339,"sha256":"fba9e4496d79c376317229a92a905be4351f5487e3db2a91d2287826db2bc7e3"} +{"corpus":"Rainier.bmp","level":7,"originalSizeBytes":6220854,"compressedSizeBytes":3282047,"singleRunMs":126.131032,"sha256":"50d60b742c7b4bfdde3d0a3a6893995cace792bbad1dd85e475e40c4dc2c0221"} +{"corpus":"Rainier.bmp","level":8,"originalSizeBytes":6220854,"compressedSizeBytes":3274905,"singleRunMs":140.425514,"sha256":"d151041825a26ae58bd43d4dc8425663e8587cbfd23a49bf4023dd74d5a414c6"} +{"corpus":"Rainier.bmp","level":9,"originalSizeBytes":6220854,"compressedSizeBytes":3255198,"singleRunMs":4235.598236,"sha256":"e67eda98521873e7a12e80ef1c3e298e342000a7b16a0d297a599a2f3bf7cf80"} +{"corpus":"Maltese.bmp","level":0,"originalSizeBytes":16427390,"compressedSizeBytes":16428645,"singleRunMs":6.525581,"sha256":"d872a98f975735016f16578b716b5c874f98e85abc101426d1142dd3a5c096d6"} +{"corpus":"Maltese.bmp","level":1,"originalSizeBytes":16427390,"compressedSizeBytes":8344362,"singleRunMs":311.848320,"sha256":"fbb73b9022879442d4e1f1ecb02baa6b1ac77119aafde5151b559e0b417dd98c"} +{"corpus":"Maltese.bmp","level":2,"originalSizeBytes":16427390,"compressedSizeBytes":7762283,"singleRunMs":353.512485,"sha256":"382e0863aa03871829f20b35a7d9f69c29108bbfcca7dd1d0097f782be3f8a2b"} +{"corpus":"Maltese.bmp","level":3,"originalSizeBytes":16427390,"compressedSizeBytes":7494606,"singleRunMs":390.544770,"sha256":"387c7f415e7da413a670c5ec9589ef69e744bf442195d53f60996d04c2d661dc"} +{"corpus":"Maltese.bmp","level":4,"originalSizeBytes":16427390,"compressedSizeBytes":7272625,"singleRunMs":361.597747,"sha256":"799d4909f60c7fa4262539af0c182ecf99fae272ed6b031524cf86ff2cef7693"} +{"corpus":"Maltese.bmp","level":5,"originalSizeBytes":16427390,"compressedSizeBytes":7265831,"singleRunMs":466.553285,"sha256":"d62521d1d682ba1afa24845265fcb768883997c5425775d8630b2feaab128464"} +{"corpus":"Maltese.bmp","level":6,"originalSizeBytes":16427390,"compressedSizeBytes":7158472,"singleRunMs":471.089058,"sha256":"cb10f06b36e0eaf03ebf81b8743a321d751979f5e671deb340405dfa6b8986b1"} +{"corpus":"Maltese.bmp","level":7,"originalSizeBytes":16427390,"compressedSizeBytes":7157735,"singleRunMs":476.832862,"sha256":"9ac4463c11aeaac8cc3ca316115118a45d1cec7fc7807cb6da67b58630de2f6b"} +{"corpus":"Maltese.bmp","level":8,"originalSizeBytes":16427390,"compressedSizeBytes":7125327,"singleRunMs":475.871902,"sha256":"a05331809efe04ca4434c5bfd57592571a22c5d30211715d6e24c3828903c640"} +{"corpus":"Maltese.bmp","level":9,"originalSizeBytes":16427390,"compressedSizeBytes":6860004,"singleRunMs":1513.294170,"sha256":"82d5f7e47a65a6f9f9d47068438b5472ec68cd2b6ba1827f93d7dd18a6ce0083"} +{"corpus":"Sunrise.bmp","level":0,"originalSizeBytes":52344054,"compressedSizeBytes":52348049,"singleRunMs":22.612684,"sha256":"4ab78a3e1ba97388ff3dd5e00d9e134bceeb1b5eb3edc7aaf7845c1377fea548"} +{"corpus":"Sunrise.bmp","level":1,"originalSizeBytes":52344054,"compressedSizeBytes":27793016,"singleRunMs":820.017802,"sha256":"7028cd0b1e7d73172e76063b6004aedee371667bca442e8a68ca718f36dac355"} +{"corpus":"Sunrise.bmp","level":2,"originalSizeBytes":52344054,"compressedSizeBytes":27471887,"singleRunMs":1017.839734,"sha256":"38fe2dd9e078be3c88adf86d15cc2da3187ea4c8919a73284f431e68dd9b7392"} +{"corpus":"Sunrise.bmp","level":3,"originalSizeBytes":52344054,"compressedSizeBytes":27404419,"singleRunMs":1229.482338,"sha256":"158c5cb3eb8d7023dc234ec5ae5e4e0d64be93f8c0f2f250bf05da65d5c9aff3"} +{"corpus":"Sunrise.bmp","level":4,"originalSizeBytes":52344054,"compressedSizeBytes":27107867,"singleRunMs":1151.271124,"sha256":"c42c56683342f532ce402a90d066e23d688a19221200648c26ce3b11621cc2e0"} +{"corpus":"Sunrise.bmp","level":5,"originalSizeBytes":52344054,"compressedSizeBytes":27096750,"singleRunMs":1374.580351,"sha256":"734bc825d4f1374115b66c64e1f56edf46c8978185ddaecffd9adc87a2e4c12e"} +{"corpus":"Sunrise.bmp","level":6,"originalSizeBytes":52344054,"compressedSizeBytes":26838825,"singleRunMs":1517.752687,"sha256":"34a1e5b94bf2344b565dc7b11b44f6908bda919a1fea479b2b2e0f557fd26346"} +{"corpus":"Sunrise.bmp","level":7,"originalSizeBytes":52344054,"compressedSizeBytes":26827604,"singleRunMs":1976.267488,"sha256":"cb202e01985166da6621d97ab386edff2eb4274eb8f1237aff36390543dcf18c"} +{"corpus":"Sunrise.bmp","level":8,"originalSizeBytes":52344054,"compressedSizeBytes":26728454,"singleRunMs":1945.606578,"sha256":"7570e8999cbda1a50c9693338f4a11dcf5aed8f6f45ff4cc1def7c3ee945541b"} +{"corpus":"Sunrise.bmp","level":9,"originalSizeBytes":52344054,"compressedSizeBytes":26083978,"singleRunMs":14975.151610,"sha256":"c0bb6198bb9ef637a1cc6bb3007c1ea2b4be493fa772ee4312e47d2fe05ab57c"} +{"corpus":"compressed_MVT.pbf","level":0,"originalSizeBytes":146224,"compressedSizeBytes":146239,"singleRunMs":0.057595,"sha256":"d8239f92d78f0d7fc3e9e9d8557e35365184e7d8c7f432339a8375c422a61c13"} +{"corpus":"compressed_MVT.pbf","level":1,"originalSizeBytes":146224,"compressedSizeBytes":95812,"singleRunMs":2.589306,"sha256":"8e921cc121ff9a262119bd7a2124a36039b95a26a5095349d08ea9b776c0ba34"} +{"corpus":"compressed_MVT.pbf","level":2,"originalSizeBytes":146224,"compressedSizeBytes":94608,"singleRunMs":2.925776,"sha256":"52efa74d70a15df6fa9d67da07da404b7e4628f895f65ddaa94148161762c45c"} +{"corpus":"compressed_MVT.pbf","level":3,"originalSizeBytes":146224,"compressedSizeBytes":94345,"singleRunMs":3.104935,"sha256":"a4090d9493e7e896ce6bc3f1c454e23738aa2e35e5418abb8d98c9f6dafaec94"} +{"corpus":"compressed_MVT.pbf","level":4,"originalSizeBytes":146224,"compressedSizeBytes":93369,"singleRunMs":3.321581,"sha256":"41844dbfb741b35e7e91c17ad039e1439e9601af58a3f70c6a83cac1e5f9491e"} +{"corpus":"compressed_MVT.pbf","level":5,"originalSizeBytes":146224,"compressedSizeBytes":93229,"singleRunMs":3.899664,"sha256":"169dee1b2849bae5fbfcdfd0daaece65729fe589980485d0b441c19050dd97b8"} +{"corpus":"compressed_MVT.pbf","level":6,"originalSizeBytes":146224,"compressedSizeBytes":92605,"singleRunMs":3.968359,"sha256":"87d498941e1d7cae4ee47930a9becc40606244a9e9e4c06d0ef21a3434093459"} +{"corpus":"compressed_MVT.pbf","level":7,"originalSizeBytes":146224,"compressedSizeBytes":92610,"singleRunMs":4.043387,"sha256":"5eb82ecc19fbb18428eceb3e508c2dfdbe4a648bc52733e8db70bd223c732f65"} +{"corpus":"compressed_MVT.pbf","level":8,"originalSizeBytes":146224,"compressedSizeBytes":92631,"singleRunMs":4.437293,"sha256":"00be763dadfed2e2d09467a7da0f564897ddc75421fab3bf3150836470ed0a62"} +{"corpus":"compressed_MVT.pbf","level":9,"originalSizeBytes":146224,"compressedSizeBytes":91400,"singleRunMs":11.638608,"sha256":"c3f8bcf3e6f73717dc8b242e96b3324b9f0b30dfe2e06fbb8e56f89128c22adb"} diff --git a/performance/2026-09-09-dynamic/before-jmh.json b/performance/2026-09-09-dynamic/before-jmh.json new file mode 100644 index 0000000..7d236a0 --- /dev/null +++ b/performance/2026-09-09-dynamic/before-jmh.json @@ -0,0 +1,380 @@ +[ + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "simpleText" + }, + "primaryMetric" : { + "score" : 2.7203772831719315E-5, + "scoreError" : 2.4728033893405515E-6, + "scoreConfidence" : [ + 2.4730969442378765E-5, + 2.9676576221059866E-5 + ], + "scorePercentiles" : { + "0.0" : 2.6647192353803117E-5, + "50.0" : 2.6857865060823332E-5, + "90.0" : 2.81695109283461E-5, + "95.0" : 2.81695109283461E-5, + "99.0" : 2.81695109283461E-5, + "99.9" : 2.81695109283461E-5, + "99.99" : 2.81695109283461E-5, + "99.999" : 2.81695109283461E-5, + "99.9999" : 2.81695109283461E-5, + "100.0" : 2.81695109283461E-5 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 2.81695109283461E-5, + 2.679433043990784E-5, + 2.6857865060823332E-5, + 2.7549965375716175E-5, + 2.6647192353803117E-5 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "text" + }, + "primaryMetric" : { + "score" : 0.19223283826666665, + "scoreError" : 0.004608719940206378, + "scoreConfidence" : [ + 0.18762411832646028, + 0.19684155820687302 + ], + "scorePercentiles" : { + "0.0" : 0.19101506583333333, + "50.0" : 0.1922419345, + "90.0" : 0.19371265383333333, + "95.0" : 0.19371265383333333, + "99.0" : 0.19371265383333333, + "99.9" : 0.19371265383333333, + "99.99" : 0.19371265383333333, + "99.999" : 0.19371265383333333, + "99.9999" : 0.19371265383333333, + "100.0" : 0.19371265383333333 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 0.19101506583333333, + 0.1910922, + 0.1922419345, + 0.19310233716666667, + 0.19371265383333333 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "model3D" + }, + "primaryMetric" : { + "score" : 9.687598398050543E-5, + "scoreError" : 4.441203208452849E-6, + "scoreConfidence" : [ + 9.243478077205258E-5, + 1.0131718718895828E-4 + ], + "scorePercentiles" : { + "0.0" : 9.524352980384688E-5, + "50.0" : 9.690634576632436E-5, + "90.0" : 9.838484753098564E-5, + "95.0" : 9.838484753098564E-5, + "99.0" : 9.838484753098564E-5, + "99.9" : 9.838484753098564E-5, + "99.99" : 9.838484753098564E-5, + "99.999" : 9.838484753098564E-5, + "99.9999" : 9.838484753098564E-5, + "100.0" : 9.838484753098564E-5 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 9.524352980384688E-5, + 9.838484753098564E-5, + 9.690634576632436E-5, + 9.735513304136253E-5, + 9.649006376000771E-5 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "Rainier.bmp" + }, + "primaryMetric" : { + "score" : 2.551168353, + "scoreError" : 0.5400113148623004, + "scoreConfidence" : [ + 2.0111570381376995, + 3.0911796678623005 + ], + "scorePercentiles" : { + "0.0" : 2.474772922, + "50.0" : 2.500730151, + "90.0" : 2.800922797, + "95.0" : 2.800922797, + "99.0" : 2.800922797, + "99.9" : 2.800922797, + "99.99" : 2.800922797, + "99.999" : 2.800922797, + "99.9999" : 2.800922797, + "100.0" : 2.800922797 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 2.500730151, + 2.503046614, + 2.474772922, + 2.476369281, + 2.800922797 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "Maltese.bmp" + }, + "primaryMetric" : { + "score" : 1.2069042516, + "scoreError" : 0.07625138081262017, + "scoreConfidence" : [ + 1.1306528707873797, + 1.28315563241262 + ], + "scorePercentiles" : { + "0.0" : 1.190969672, + "50.0" : 1.196923624, + "90.0" : 1.234775154, + "95.0" : 1.234775154, + "99.0" : 1.234775154, + "99.9" : 1.234775154, + "99.99" : 1.234775154, + "99.999" : 1.234775154, + "99.9999" : 1.234775154, + "100.0" : 1.234775154 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 1.220696166, + 1.234775154, + 1.191156642, + 1.196923624, + 1.190969672 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "Sunrise.bmp" + }, + "primaryMetric" : { + "score" : 11.385807222599999, + "scoreError" : 0.6233573844313627, + "scoreConfidence" : [ + 10.762449838168635, + 12.009164607031362 + ], + "scorePercentiles" : { + "0.0" : 11.255930507, + "50.0" : 11.289084607, + "90.0" : 11.570045612, + "95.0" : 11.570045612, + "99.0" : 11.570045612, + "99.9" : 11.570045612, + "99.99" : 11.570045612, + "99.999" : 11.570045612, + "99.9999" : 11.570045612, + "100.0" : 11.570045612 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 11.570045612, + 11.554908951, + 11.289084607, + 11.255930507, + 11.259066436 + ] + ] + }, + "secondaryMetrics" : { + } + }, + { + "jmhVersion" : "1.37", + "benchmark" : "com.rafambn.kflate.benchmark.CompressionBenchmarks.rawDeflateCompression", + "mode" : "avgt", + "threads" : 1, + "forks" : 1, + "jvm" : "/home/rafael/.jdks/jbr-17.0.14/bin/java", + "jvmArgs" : [ + ], + "jdkVersion" : "17.0.14", + "vmName" : "OpenJDK 64-Bit Server VM", + "vmVersion" : "17.0.14+1-b1367.22", + "warmupIterations" : 3, + "warmupTime" : "1 s", + "warmupBatchSize" : 1, + "measurementIterations" : 5, + "measurementTime" : "1 s", + "measurementBatchSize" : 1, + "params" : { + "corpus" : "compressed_MVT.pbf" + }, + "primaryMetric" : { + "score" : 0.009324682879700792, + "scoreError" : 4.5141358132523053E-4, + "scoreConfidence" : [ + 0.008873269298375562, + 0.009776096461026023 + ], + "scorePercentiles" : { + "0.0" : 0.00922847810091743, + "50.0" : 0.009319085546296296, + "90.0" : 0.009516081198113207, + "95.0" : 0.009516081198113207, + "99.0" : 0.009516081198113207, + "99.9" : 0.009516081198113207, + "99.99" : 0.009516081198113207, + "99.999" : 0.009516081198113207, + "99.9999" : 0.009516081198113207, + "100.0" : 0.009516081198113207 + }, + "scoreUnit" : "s/op", + "rawData" : [ + [ + 0.009516081198113207, + 0.00922847810091743, + 0.009229693256880734, + 0.009330076296296296, + 0.009319085546296296 + ] + ] + }, + "secondaryMetrics" : { + } + } +] diff --git a/performance/2026-09-09-dynamic/before-sizes.jsonl b/performance/2026-09-09-dynamic/before-sizes.jsonl new file mode 100644 index 0000000..6b0a261 --- /dev/null +++ b/performance/2026-09-09-dynamic/before-sizes.jsonl @@ -0,0 +1,70 @@ +{"corpus":"simpleText","level":0,"originalSizeBytes":100,"compressedSizeBytes":105,"singleRunMs":18.721607} +{"corpus":"simpleText","level":1,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":10.375607} +{"corpus":"simpleText","level":2,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.346866} +{"corpus":"simpleText","level":3,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.426491} +{"corpus":"simpleText","level":4,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.288781} +{"corpus":"simpleText","level":5,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.294199} +{"corpus":"simpleText","level":6,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.256687} +{"corpus":"simpleText","level":7,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.217747} +{"corpus":"simpleText","level":8,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.213022} +{"corpus":"simpleText","level":9,"originalSizeBytes":100,"compressedSizeBytes":84,"singleRunMs":0.510794} +{"corpus":"text","level":0,"originalSizeBytes":1232923,"compressedSizeBytes":1233018,"singleRunMs":4.634060} +{"corpus":"text","level":1,"originalSizeBytes":1232923,"compressedSizeBytes":599813,"singleRunMs":54.476717} +{"corpus":"text","level":2,"originalSizeBytes":1232923,"compressedSizeBytes":581519,"singleRunMs":33.454095} +{"corpus":"text","level":3,"originalSizeBytes":1232923,"compressedSizeBytes":565252,"singleRunMs":34.883134} +{"corpus":"text","level":4,"originalSizeBytes":1232923,"compressedSizeBytes":531466,"singleRunMs":59.907435} +{"corpus":"text","level":5,"originalSizeBytes":1232923,"compressedSizeBytes":521837,"singleRunMs":61.611316} +{"corpus":"text","level":6,"originalSizeBytes":1232923,"compressedSizeBytes":506455,"singleRunMs":76.163221} +{"corpus":"text","level":7,"originalSizeBytes":1232923,"compressedSizeBytes":506097,"singleRunMs":78.619466} +{"corpus":"text","level":8,"originalSizeBytes":1232923,"compressedSizeBytes":513489,"singleRunMs":83.872443} +{"corpus":"text","level":9,"originalSizeBytes":1232923,"compressedSizeBytes":492523,"singleRunMs":220.517381} +{"corpus":"model3D","level":0,"originalSizeBytes":2478,"compressedSizeBytes":2483,"singleRunMs":0.054391} +{"corpus":"model3D","level":1,"originalSizeBytes":2478,"compressedSizeBytes":2169,"singleRunMs":0.236631} +{"corpus":"model3D","level":2,"originalSizeBytes":2478,"compressedSizeBytes":2168,"singleRunMs":0.159924} +{"corpus":"model3D","level":3,"originalSizeBytes":2478,"compressedSizeBytes":2166,"singleRunMs":0.143489} +{"corpus":"model3D","level":4,"originalSizeBytes":2478,"compressedSizeBytes":2165,"singleRunMs":0.133548} +{"corpus":"model3D","level":5,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.726203} +{"corpus":"model3D","level":6,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.277670} +{"corpus":"model3D","level":7,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.243557} +{"corpus":"model3D","level":8,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.184029} +{"corpus":"model3D","level":9,"originalSizeBytes":2478,"compressedSizeBytes":2153,"singleRunMs":0.404074} +{"corpus":"Rainier.bmp","level":0,"originalSizeBytes":6220854,"compressedSizeBytes":6221329,"singleRunMs":4.097972} +{"corpus":"Rainier.bmp","level":1,"originalSizeBytes":6220854,"compressedSizeBytes":3387685,"singleRunMs":127.041113} +{"corpus":"Rainier.bmp","level":2,"originalSizeBytes":6220854,"compressedSizeBytes":3357387,"singleRunMs":101.260474} +{"corpus":"Rainier.bmp","level":3,"originalSizeBytes":6220854,"compressedSizeBytes":3345679,"singleRunMs":106.363578} +{"corpus":"Rainier.bmp","level":4,"originalSizeBytes":6220854,"compressedSizeBytes":3325593,"singleRunMs":100.669595} +{"corpus":"Rainier.bmp","level":5,"originalSizeBytes":6220854,"compressedSizeBytes":3313388,"singleRunMs":105.538266} +{"corpus":"Rainier.bmp","level":6,"originalSizeBytes":6220854,"compressedSizeBytes":3283450,"singleRunMs":113.997284} +{"corpus":"Rainier.bmp","level":7,"originalSizeBytes":6220854,"compressedSizeBytes":3282047,"singleRunMs":120.376039} +{"corpus":"Rainier.bmp","level":8,"originalSizeBytes":6220854,"compressedSizeBytes":3274905,"singleRunMs":118.865381} +{"corpus":"Rainier.bmp","level":9,"originalSizeBytes":6220854,"compressedSizeBytes":3258570,"singleRunMs":3625.149389} +{"corpus":"Maltese.bmp","level":0,"originalSizeBytes":16427390,"compressedSizeBytes":16428645,"singleRunMs":6.704834} +{"corpus":"Maltese.bmp","level":1,"originalSizeBytes":16427390,"compressedSizeBytes":8344362,"singleRunMs":287.839174} +{"corpus":"Maltese.bmp","level":2,"originalSizeBytes":16427390,"compressedSizeBytes":7762283,"singleRunMs":334.470960} +{"corpus":"Maltese.bmp","level":3,"originalSizeBytes":16427390,"compressedSizeBytes":7494606,"singleRunMs":371.202987} +{"corpus":"Maltese.bmp","level":4,"originalSizeBytes":16427390,"compressedSizeBytes":7272625,"singleRunMs":395.378098} +{"corpus":"Maltese.bmp","level":5,"originalSizeBytes":16427390,"compressedSizeBytes":7265831,"singleRunMs":509.528066} +{"corpus":"Maltese.bmp","level":6,"originalSizeBytes":16427390,"compressedSizeBytes":7158472,"singleRunMs":523.034253} +{"corpus":"Maltese.bmp","level":7,"originalSizeBytes":16427390,"compressedSizeBytes":7157735,"singleRunMs":526.984351} +{"corpus":"Maltese.bmp","level":8,"originalSizeBytes":16427390,"compressedSizeBytes":7125327,"singleRunMs":524.641283} +{"corpus":"Maltese.bmp","level":9,"originalSizeBytes":16427390,"compressedSizeBytes":7034092,"singleRunMs":1436.734506} +{"corpus":"Sunrise.bmp","level":0,"originalSizeBytes":52344054,"compressedSizeBytes":52348049,"singleRunMs":31.612486} +{"corpus":"Sunrise.bmp","level":1,"originalSizeBytes":52344054,"compressedSizeBytes":27793016,"singleRunMs":887.391514} +{"corpus":"Sunrise.bmp","level":2,"originalSizeBytes":52344054,"compressedSizeBytes":27471887,"singleRunMs":1064.576845} +{"corpus":"Sunrise.bmp","level":3,"originalSizeBytes":52344054,"compressedSizeBytes":27404419,"singleRunMs":1166.086238} +{"corpus":"Sunrise.bmp","level":4,"originalSizeBytes":52344054,"compressedSizeBytes":27107867,"singleRunMs":1250.581032} +{"corpus":"Sunrise.bmp","level":5,"originalSizeBytes":52344054,"compressedSizeBytes":27096750,"singleRunMs":1511.964986} +{"corpus":"Sunrise.bmp","level":6,"originalSizeBytes":52344054,"compressedSizeBytes":26838825,"singleRunMs":1479.025315} +{"corpus":"Sunrise.bmp","level":7,"originalSizeBytes":52344054,"compressedSizeBytes":26827604,"singleRunMs":1687.182227} +{"corpus":"Sunrise.bmp","level":8,"originalSizeBytes":52344054,"compressedSizeBytes":26728454,"singleRunMs":1866.351752} +{"corpus":"Sunrise.bmp","level":9,"originalSizeBytes":52344054,"compressedSizeBytes":26372269,"singleRunMs":12143.996321} +{"corpus":"compressed_MVT.pbf","level":0,"originalSizeBytes":146224,"compressedSizeBytes":146239,"singleRunMs":0.056884} +{"corpus":"compressed_MVT.pbf","level":1,"originalSizeBytes":146224,"compressedSizeBytes":95812,"singleRunMs":2.498114} +{"corpus":"compressed_MVT.pbf","level":2,"originalSizeBytes":146224,"compressedSizeBytes":94608,"singleRunMs":2.921274} +{"corpus":"compressed_MVT.pbf","level":3,"originalSizeBytes":146224,"compressedSizeBytes":94345,"singleRunMs":3.426504} +{"corpus":"compressed_MVT.pbf","level":4,"originalSizeBytes":146224,"compressedSizeBytes":93369,"singleRunMs":3.443246} +{"corpus":"compressed_MVT.pbf","level":5,"originalSizeBytes":146224,"compressedSizeBytes":93229,"singleRunMs":3.893521} +{"corpus":"compressed_MVT.pbf","level":6,"originalSizeBytes":146224,"compressedSizeBytes":92605,"singleRunMs":4.154555} +{"corpus":"compressed_MVT.pbf","level":7,"originalSizeBytes":146224,"compressedSizeBytes":92610,"singleRunMs":4.015288} +{"corpus":"compressed_MVT.pbf","level":8,"originalSizeBytes":146224,"compressedSizeBytes":92631,"singleRunMs":4.439951} +{"corpus":"compressed_MVT.pbf","level":9,"originalSizeBytes":146224,"compressedSizeBytes":91727,"singleRunMs":8.610094} diff --git a/performance/2026-09-09-dynamic/native_bench.py b/performance/2026-09-09-dynamic/native_bench.py new file mode 100644 index 0000000..7a66ddc --- /dev/null +++ b/performance/2026-09-09-dynamic/native_bench.py @@ -0,0 +1,38 @@ +import json +from pathlib import Path +import subprocess +import sys + +binary = str(Path(sys.argv[1]).resolve()) +directory = Path(sys.argv[2]).resolve() +directory.mkdir(parents=True, exist_ok=True) +config = directory / 'runner.cfg' +config.write_text('\n'.join([ + 'name:ratio', f'reportFile:{directory}/benchmark.json', + 'traceFormat:text', 'reportFormat:json', + 'include:' + (sys.argv[5] if len(sys.argv) > 5 else '.*CompressionBenchmarks.rawDeflateCompression'), + f'warmups:{sys.argv[3] if len(sys.argv) > 3 else 3}', + f'iterations:{sys.argv[4] if len(sys.argv) > 4 else 5}', + 'iterationTime:1', 'iterationTimeUnit:sec', + 'outputTimeUnit:sec', 'mode:avgt', +])) + +def run(action, *args): + subprocess.run([binary, str(config), action, str(directory / 'trace.xml'), *map(str, args)], check=True) + +run('--list', directory) +configs = sorted(directory.glob('*.txt')) +expected = 14 if len(sys.argv) > 5 and 'Decompression' in sys.argv[5] else 7 +assert len(configs) == expected, configs +results = [] +for benchmark_config in configs: + samples = benchmark_config.with_suffix('.samples') + run('--benchmark', benchmark_config, samples) + values = samples.read_text().strip() + assert values and 'null' not in values + results.append(f'{benchmark_config}: {values}') +combined = directory / 'results' +combined.write_text('\n'.join(results)) +run('--store-results', combined) +rows = json.loads((directory / 'benchmark.json').read_text()) +assert len(rows) == expected