Skip to content

Commit d4acd1a

Browse files
authored
Add an application that compresses input data (#79)
This lets users provide their own data so they can quickly see what kind of compression ratio that could expect from StreamVByte on their own workload.
1 parent 1079110 commit d4acd1a

3 files changed

Lines changed: 102 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ dynunit
33
writeseq
44
perf
55
example
6+
compress_decimal_encoded_integers
67

78
# Object files
89
*.o

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ shuffle_tables: ./utils/shuffle_tables.c
7171
example: ./examples/example.c $(HEADERS) $(OBJECTS)
7272
$(CC) $(CFLAGS) -o example ./examples/example.c -Iinclude $(OBJECTS)
7373

74+
compress_decimal_encoded_integers: ./examples/compress_decimal_encoded_integers.c $(HEADERS) $(OBJECTS)
75+
$(CC) $(CFLAGS) -o compress_decimal_encoded_integers ./examples/compress_decimal_encoded_integers.c -Iinclude $(OBJECTS)
76+
7477
perf: ./tests/perf.c $(HEADERS) $(OBJECTS)
7578
$(CC) $(CFLAGS) -o perf ./tests/perf.c -Iinclude $(OBJECTS) -lm
7679

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include <assert.h>
2+
#include <fcntl.h>
3+
#include <inttypes.h>
4+
#include <stdint.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <sys/stat.h>
8+
#include <unistd.h>
9+
10+
#include "streamvbyte.h"
11+
12+
#define MAX_INTEGERS 10000
13+
14+
size_t read_integers(const char* filename, uint32_t* buffer);
15+
void write_file_or_die(const char* filename, ssize_t length, const uint8_t* data);
16+
17+
// This application reads decimal-encoded integers from an input file
18+
// and compresses them using StreamVByte. There's a fairly low limit
19+
// on how much data is allowed to be in the input file because this
20+
// application is, for the moment, intended to measure the compression
21+
// ratio.
22+
// If the second argument, the output filename, is absent, then this
23+
// application does not write the compressed data to the file system,
24+
// but it still prints out information about the compression ratio.
25+
int main(int argc, char *argv[]){
26+
if(argc != 2 && argc != 3) {
27+
fprintf(stderr, "Expected arguments: IN_FILENAME, [OUT_FILENAME]\n");
28+
exit(EXIT_FAILURE);
29+
}
30+
char* in_filename = argv[1];
31+
char* out_filename = NULL;
32+
if(argc == 3) {
33+
out_filename = argv[2];
34+
}
35+
36+
uint32_t input[MAX_INTEGERS] = {0};
37+
size_t count = read_integers(in_filename, input);
38+
uint8_t* compressed_buffer = malloc(streamvbyte_max_compressedbytes(count));
39+
size_t compressed_size = streamvbyte_encode(input, count, compressed_buffer);
40+
size_t millibytes_per_element = (1000 * compressed_size) / count;
41+
fprintf(
42+
stdout,
43+
"Compressed %llu 32-bit integers to %llu bytes (%llu.%03llu bytes per integer)\n",
44+
(long long unsigned)count,
45+
(long long unsigned)compressed_size,
46+
(long long unsigned)(millibytes_per_element / 1000),
47+
(long long unsigned)(millibytes_per_element % 1000)
48+
);
49+
if(out_filename != NULL) {
50+
fprintf(stdout, "Writing file to %s\n", out_filename);
51+
write_file_or_die(out_filename, compressed_size, compressed_buffer);
52+
}
53+
return 0;
54+
}
55+
56+
size_t read_integers(const char* filename, uint32_t* buffer) {
57+
FILE* fp = fopen(filename, "r");
58+
if (!fp) {
59+
fprintf(stderr, "Error: cannot open file '%s'\n", filename);
60+
exit(1);
61+
}
62+
63+
size_t count = 0;
64+
uint32_t value;
65+
while (fscanf(fp, "%" SCNu32, &value) == 1) {
66+
if (count >= MAX_INTEGERS) {
67+
fprintf(stderr, "Fatal: more than %d integers in file\n", MAX_INTEGERS);
68+
fclose(fp);
69+
exit(1);
70+
}
71+
buffer[count++] = value;
72+
}
73+
74+
fclose(fp);
75+
return count;
76+
}
77+
78+
int open_trunc_or_die(const char* filename) {
79+
int out_fd = open(filename, O_TRUNC | O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
80+
if (out_fd == -1) {
81+
perror("Could not open output file");
82+
exit(EXIT_FAILURE);
83+
}
84+
return out_fd;
85+
}
86+
87+
void append_or_die(int fd, ssize_t length, const uint8_t* data) {
88+
if (write(fd, data, length) != length) {
89+
fprintf(stderr, "Some kind of problem writing the output file\n");
90+
exit(EXIT_FAILURE);
91+
}
92+
}
93+
94+
void write_file_or_die(const char* filename, ssize_t length, const uint8_t* data) {
95+
int out_fd = open_trunc_or_die(filename);
96+
append_or_die(out_fd, length, data);
97+
close(out_fd);
98+
}

0 commit comments

Comments
 (0)