#define _CRT_SECURE_NO_WARNINGS #include #define CPUTIME_IMPLEMENTATION #include "../../test/cputime.h" #include "../../ufbx.h" #include #include #include #include #define UFBX_RETAIN 1 int inflate_memory(const void *src, int srcLen, void *dst, int dstLen) { z_stream strm = {0}; strm.total_in = strm.avail_in = srcLen; strm.total_out = strm.avail_out = dstLen; strm.next_in = (Bytef *) src; strm.next_out = (Bytef *) dst; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; int err = -1; int ret = -1; err = inflateInit2(&strm, 15); if (err == Z_OK) { err = inflate(&strm, Z_FINISH); if (err == Z_STREAM_END) { ret = strm.total_out; } else { inflateEnd(&strm); return err; } } else { inflateEnd(&strm); return err; } inflateEnd(&strm); return ret; } std::vector read_file(const char *path) { FILE *f = fopen(path, "rb"); fseek(f, 0, SEEK_END); std::vector data; data.resize(ftell(f)); fseek(f, 0, SEEK_SET); fread(data.data(), 1, data.size(), f); fclose(f); return data; } struct deflate_stream { const void *data; size_t compressed_size; size_t decompressed_size; uint64_t zlib_time = UINT64_MAX; uint64_t ufbx_time = UINT64_MAX; }; int main(int argc, char **argv) { std::vector data = read_file(argv[1]); std::vector streams; std::vector dst_buf; cputime_begin_init(); size_t max_decompressed_size = 0; for (size_t offset = 0; offset < data.size(); ) { deflate_stream stream; stream.compressed_size = *(uint32_t*)(data.data() + offset + 0); stream.decompressed_size = *(uint32_t*)(data.data() + offset + 4); stream.data = data.data() + offset + 8; offset += 8 + stream.compressed_size; if (stream.decompressed_size > max_decompressed_size) { max_decompressed_size = stream.decompressed_size; } streams.push_back(stream); } if (argc > 2) { deflate_stream single = streams[atoi(argv[2])]; streams.clear(); streams.push_back(single); } size_t runs = 3; if (argc > 3) { runs = (size_t)atoi(argv[3]); } dst_buf.resize(max_decompressed_size); for (size_t i = 0; i < runs; i++) { for (deflate_stream &stream : streams) { uint64_t begin = cputime_cpu_tick(); int ret = inflate_memory(stream.data, (int)stream.compressed_size, dst_buf.data(), (int)stream.decompressed_size); assert(ret == stream.decompressed_size); uint64_t end = cputime_cpu_tick(); if (argc > 20) { fwrite(dst_buf.data(), 1, stream.decompressed_size, stdout); } stream.zlib_time = std::min(stream.zlib_time, end - begin); } #if UFBX_RETAIN ufbx_inflate_retain retain; retain.initialized = false; #endif for (deflate_stream &stream : streams) { uint64_t begin = cputime_cpu_tick(); #if !UFBX_RETAIN ufbx_inflate_retain retain; retain.initialized = false; #endif ufbx_inflate_input input = { }; engine.input.data_size = engine.input.total_size = stream.compressed_size; engine.input.data = stream.data; ptrdiff_t ret = ufbx_inflate(dst_buf.data(), stream.decompressed_size, &input, &retain); assert(ret == stream.decompressed_size); if (argc > 20) { fwrite(dst_buf.data(), 1, stream.decompressed_size, stdout); } uint64_t end = cputime_cpu_tick(); stream.ufbx_time = std::min(stream.ufbx_time, end - begin); } } cputime_end_init(); uint32_t index = 0; for (deflate_stream &stream : streams) { double ufbx_sec = cputime_cpu_delta_to_sec(NULL, stream.ufbx_time); double zlib_sec = cputime_cpu_delta_to_sec(NULL, stream.zlib_time); double ufbx_cbp = (double)stream.ufbx_time / (double)stream.decompressed_size; double zlib_cbp = (double)stream.zlib_time / (double)stream.decompressed_size; printf("[%6.2f] %3u: %10zu -> %10zu bytes: %8.4fms (%6.2fcy/b) vs %8.4fms (%6.2fcy/b)\n", ufbx_sec / zlib_sec * 100.0, index, stream.compressed_size, stream.decompressed_size, ufbx_sec*1e3, ufbx_cbp, zlib_sec*1e3, zlib_cbp); index++; } return 0; }