aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorGravatar Runxi Yu2025-11-19 08:00:00 +0800
committerGravatar Runxi Yu2025-11-19 08:00:00 +0800
commit64b2b1acdec2b332cf62080aeafa89abf9e25826 (patch)
treee8b3b73a0860c27c7aa5d25f1b8e6954bec978c7 /internal
parentImport flate (diff)
signatureNo signature
Add zlib test data
Diffstat (limited to 'internal')
-rw-r--r--internal/bench/.clang-format24
-rw-r--r--internal/bench/.gitignore3
-rw-r--r--internal/bench/Makefile12
-rw-r--r--internal/bench/README1
-rw-r--r--internal/bench/compress.c134
-rw-r--r--internal/bench/decompress.go48
6 files changed, 222 insertions, 0 deletions
diff --git a/internal/bench/.clang-format b/internal/bench/.clang-format
new file mode 100644
index 00000000..caada788
--- /dev/null
+++ b/internal/bench/.clang-format
@@ -0,0 +1,24 @@
+BasedOnStyle: LLVM
+UseTab: Always
+IndentWidth: 8
+TabWidth: 8
+ContinuationIndentWidth: 8
+
+AccessModifierOffset: -8
+IndentCaseBlocks: true
+IndentCaseLabels: true
+IndentGotoLabels: false
+IndentPPDirectives: AfterHash
+NamespaceIndentation: None
+
+AlignAfterOpenBracket: DontAlign
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignConsecutiveMacros: false
+AlignEscapedNewlines: DontAlign
+AlignOperands: DontAlign
+AlignTrailingComments: false
+
+BreakBeforeBraces: Linux
+AllowShortFunctionsOnASingleLine: Empty
+ColumnLimit: 0
diff --git a/internal/bench/.gitignore b/internal/bench/.gitignore
new file mode 100644
index 00000000..5233684d
--- /dev/null
+++ b/internal/bench/.gitignore
@@ -0,0 +1,3 @@
+/*.test.zlib*
+/*.test.bin*
+/*.elf
diff --git a/internal/bench/Makefile b/internal/bench/Makefile
new file mode 100644
index 00000000..f2b3f316
--- /dev/null
+++ b/internal/bench/Makefile
@@ -0,0 +1,12 @@
+.PHONY: all clean
+
+all: compress.elf decompress.elf
+
+clean:
+ rm -f *.elf
+
+compress.elf: compress.c
+ $(CC) $(CFLAGS) -o compress.elf compress.c -lz-ng
+
+decompress.elf: decompress.go
+ go build -o decompress.elf decompress.go
diff --git a/internal/bench/README b/internal/bench/README
new file mode 100644
index 00000000..bbf82cd3
--- /dev/null
+++ b/internal/bench/README
@@ -0,0 +1 @@
+This is a temporary directory we use to test zlib performance.
diff --git a/internal/bench/compress.c b/internal/bench/compress.c
new file mode 100644
index 00000000..4425c40d
--- /dev/null
+++ b/internal/bench/compress.c
@@ -0,0 +1,134 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <zlib-ng.h>
+
+int compress_file_zlib(const char *input_path, const char *output_path)
+{
+ int fd_in = -1, fd_out = -1;
+ void *mapped_data_in = MAP_FAILED;
+ void *mapped_data_out = MAP_FAILED;
+
+ fd_in = open(input_path, O_RDONLY);
+ if (fd_in == -1) {
+ perror("open input");
+ goto error;
+ }
+
+ struct stat sb;
+ if (fstat(fd_in, &sb) == -1) {
+ perror("fstat");
+ goto error;
+ }
+ size_t file_size = sb.st_size;
+
+ if (file_size == 0) {
+ fprintf(stderr, "File is empty\n");
+ goto error;
+ }
+
+ mapped_data_in = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd_in, 0);
+ if (mapped_data_in == MAP_FAILED) {
+ perror("mmap input");
+ goto error;
+ }
+
+ size_t compressed_size_bound = zng_compressBound(file_size);
+
+ fd_out = open(output_path, O_RDWR | O_CREAT | O_TRUNC, 0644);
+ if (fd_out == -1) {
+ perror("open output");
+ goto error;
+ }
+
+ if (ftruncate(fd_out, compressed_size_bound) == -1) {
+ perror("ftruncate");
+ goto error;
+ }
+
+ mapped_data_out = mmap(NULL, compressed_size_bound, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd_out, 0);
+ if (mapped_data_out == MAP_FAILED) {
+ perror("mmap output");
+ goto error;
+ }
+
+ int ret = zng_compress2(mapped_data_out, &compressed_size_bound,
+ (const unsigned char *)mapped_data_in, file_size,
+ Z_BEST_COMPRESSION);
+
+ if (ret != Z_OK) {
+ fprintf(stderr, "Compression failed: %d\n", ret);
+ goto error;
+ }
+
+ if (ftruncate(fd_out, compressed_size_bound) == -1) {
+ perror("ftruncate final");
+ goto error;
+ }
+
+ if (msync(mapped_data_out, compressed_size_bound, MS_SYNC) == -1) {
+ perror("msync");
+ goto error;
+ }
+
+ fprintf(stderr,
+ "Compressed: %s (%zu bytes) -> %s (%zu bytes), ratio: %.1f%%\n",
+ input_path, file_size, output_path, compressed_size_bound,
+ (compressed_size_bound * 100.0) / file_size);
+
+ munmap(mapped_data_in, file_size);
+ munmap(mapped_data_out, compressed_size_bound);
+ close(fd_in);
+ close(fd_out);
+ return 0;
+
+error:
+ if (mapped_data_in != MAP_FAILED)
+ munmap(mapped_data_in, file_size);
+ if (mapped_data_out != MAP_FAILED)
+ munmap(mapped_data_out, compressed_size_bound);
+ if (fd_in != -1)
+ close(fd_in);
+ if (fd_out != -1)
+ close(fd_out);
+ return -1;
+}
+
+int compress_files(const char **input_files, const char **output_files,
+ int count)
+{
+ int success_count = 0;
+
+ for (int i = 0; i < count; i++) {
+ if (compress_file_zlib(input_files[i], output_files[i]) == 0) {
+ success_count++;
+ } else {
+ fprintf(stderr, "Failed to compress: %s\n", input_files[i]);
+ }
+ }
+
+ fprintf(stderr, "Successfully compressed %d/%d files\n", success_count,
+ count);
+ return success_count;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 3 || argc % 2 != 1) {
+ fprintf(stderr,
+ "Usage: %s <input1> <output1.zlib> [input2 output2.zlib ...]\n",
+ argv[0]);
+ return 1;
+ }
+
+ int file_count = (argc - 1) / 2;
+ const char **inputs = (const char **)&argv[1];
+ const char **outputs = (const char **)&argv[1 + file_count];
+
+ return compress_files(inputs, outputs, file_count) == file_count ? 0 : 1;
+}
diff --git a/internal/bench/decompress.go b/internal/bench/decompress.go
new file mode 100644
index 00000000..c4a4d274
--- /dev/null
+++ b/internal/bench/decompress.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "os"
+
+ "git.sr.ht/~runxiyu/furgit/internal/zlib"
+)
+
+func main() {
+ if len(os.Args) != 3 {
+ fmt.Fprintf(os.Stderr, "Usage: %s <input.zlib> <output>\n", os.Args[0])
+ os.Exit(1)
+ }
+
+ inputFile := os.Args[1]
+ outputFile := os.Args[2]
+
+ in, err := os.Open(inputFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error opening input file: %v\n", err)
+ os.Exit(1)
+ }
+ defer in.Close()
+
+ out, err := os.Create(outputFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error creating output file: %v\n", err)
+ os.Exit(1)
+ }
+ defer out.Close()
+
+ reader, err := zlib.NewReader(in)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error creating zlib reader: %v\n", err)
+ os.Exit(1)
+ }
+ defer reader.Close()
+
+ _, err = io.Copy(out, reader)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error decompressing data: %v\n", err)
+ os.Exit(1)
+ }
+
+ fmt.Fprintf(os.Stderr, "Successfully decompressed %s to %s\n", inputFile, outputFile)
+}