diff options
| author | 2025-11-19 08:00:00 +0800 | |
|---|---|---|
| committer | 2025-11-19 08:00:00 +0800 | |
| commit | 64b2b1acdec2b332cf62080aeafa89abf9e25826 (patch) | |
| tree | e8b3b73a0860c27c7aa5d25f1b8e6954bec978c7 /internal | |
| parent | Import flate (diff) | |
| signature | No signature | |
Add zlib test data
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/bench/.clang-format | 24 | ||||
| -rw-r--r-- | internal/bench/.gitignore | 3 | ||||
| -rw-r--r-- | internal/bench/Makefile | 12 | ||||
| -rw-r--r-- | internal/bench/README | 1 | ||||
| -rw-r--r-- | internal/bench/compress.c | 134 | ||||
| -rw-r--r-- | internal/bench/decompress.go | 48 |
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) +} |
