2 * run_compression_benchmarks.c
4 * Program to measure compression ratio and performance of wimlib and WIMGAPI.
7 #define _WIN32_WINNT 0x0602
9 #include "wimgapi_wrapper.h"
11 #define ARRAY_LEN(A) (sizeof(A) / sizeof((A)[0]))
13 #define VOLUME L"E:\\"
14 #define INFILE L"in.wim"
16 #define OUTFILE L"out.wim"
21 fatal_wimlib_error(const wchar_t *msg, int err)
23 fwprintf(stderr, L"Error %ls: wimlib error code %d: %ls\n", msg,
24 err, wimlib_get_error_string(err));
29 get_win32_error_string(DWORD err)
31 static wchar_t buf[1024];
33 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
34 buf, ARRAY_LEN(buf), NULL);
39 fatal_win32_error(const wchar_t *msg)
41 DWORD err = GetLastError();
42 fwprintf(stderr, L"Error %ls: Win32 error code %u: %ls\n", msg,
43 err, get_win32_error_string(err));
47 static uint64_t start_time_ms;
55 wsprintf(path, L"\\\\.\\%lc:", VOLUME[0]);
57 h = CreateFile(path, GENERIC_WRITE, FILE_SHARE_VALID_FLAGS,
58 NULL, OPEN_EXISTING, 0, NULL);
60 if (!FlushFileBuffers(h))
61 fatal_win32_error(L"Unable to sync volume " VOLUME);
67 prefetch_input_wim(void)
72 ret = wimlib_open_wim(INFILE, 0, &wim);
74 fatal_wimlib_error(L"opening input WIM for prefetch", ret);
76 ret = wimlib_verify_wim(wim, 0);
78 fatal_wimlib_error(L"prefetching input WIM", ret);
88 start_time_ms = GetTickCount64();
92 verify_output_wim_with_wimlib(void)
97 ret = wimlib_open_wim(OUTFILE, 0, &wim);
99 fatal_wimlib_error(L"opening output WIM for verification with "
103 ret = wimlib_verify_wim(wim, 0);
105 fatal_wimlib_error(L"verifying output WIM with wimlib", ret);
111 verify_output_wim_with_wimgapi(void)
116 hWim = WIMCreateFile(OUTFILE, WIM_GENERIC_READ, WIM_OPEN_EXISTING,
117 WIM_FLAG_SOLID, 0, NULL);
119 fatal_win32_error(L"opening output WIM for verification with "
122 WIMSetTemporaryPath(hWim, TMPDIR);
124 hImage = WIMLoadImage(hWim, 1);
126 fatal_win32_error(L"loading WIM image for verification with "
130 CreateDirectory(OUTDIR, NULL);
132 if (!WIMApplyImage(hImage, OUTDIR, WIM_FLAG_VERIFY))
133 fatal_win32_error(L"verifying output WIM with WIMGAPI");
135 WIMCloseHandle(hImage);
136 WIMCloseHandle(hWim);
141 verify_output_wim(void)
143 verify_output_wim_with_wimlib();
144 verify_output_wim_with_wimgapi();
148 end_test(const char *description)
150 uint64_t end_time_ms = GetTickCount64();
151 HANDLE h = CreateFile(OUTFILE, 0, FILE_SHARE_VALID_FLAGS, NULL,
152 OPEN_EXISTING, 0, NULL);
153 LARGE_INTEGER compressed_size = {.QuadPart = -1};
154 GetFileSizeEx(h, &compressed_size);
156 printf("%s: %"PRIu64" in %.1fs\n", description,
157 compressed_size.QuadPart,
158 (double)(end_time_ms - start_time_ms) / 1000);
163 static const struct wimlib_test_spec {
164 const char *description;
165 enum wimlib_compression_type ctype;
169 } wimlib_test_specs[] = {
171 .description = "wimlib, LZMS (solid)",
172 .ctype = WIMLIB_COMPRESSION_TYPE_LZMS,
176 .description = "wimlib, LZMS (non-solid)",
177 .ctype = WIMLIB_COMPRESSION_TYPE_LZMS,
180 .description = "wimlib, LZX (slow)",
181 .ctype = WIMLIB_COMPRESSION_TYPE_LZX,
185 .description = "wimlib, LZX (normal)",
186 .ctype = WIMLIB_COMPRESSION_TYPE_LZX,
189 .description = "wimlib, LZX (quick)",
190 .ctype = WIMLIB_COMPRESSION_TYPE_LZX,
194 .description = "wimlib, XPRESS (slow)",
195 .ctype = WIMLIB_COMPRESSION_TYPE_XPRESS,
199 .description = "wimlib, XPRESS",
200 .ctype = WIMLIB_COMPRESSION_TYPE_XPRESS,
203 .description = "wimlib, \"WIMBoot\" (slow)",
204 .ctype = WIMLIB_COMPRESSION_TYPE_XPRESS,
209 .description = "wimlib, \"WIMBoot\"",
210 .ctype = WIMLIB_COMPRESSION_TYPE_XPRESS,
214 .description = "wimlib, None",
215 .ctype = WIMLIB_COMPRESSION_TYPE_NONE,
219 static const struct wimgapi_test_spec {
220 const char *description;
221 DWORD compressionType;
224 } wimgapi_test_specs[] = {
226 .description = "WIMGAPI, LZMS (solid)",
227 .compressionType = WIM_COMPRESS_LZMS,
231 .description = "WIMGAPI, LZX",
232 .compressionType = WIM_COMPRESS_LZX,
235 .description = "WIMGAPI, XPRESS",
236 .compressionType = WIM_COMPRESS_XPRESS,
239 .description = "WIMGAPI, \"WIMBoot\"",
240 .compressionType = WIM_COMPRESS_XPRESS,
244 .description = "WIMGAPI, None",
245 .compressionType = WIM_COMPRESS_NONE,
250 run_wimlib_test(const struct wimlib_test_spec *testspec)
255 ret = wimlib_set_default_compression_level(-1, 0);
257 fatal_wimlib_error(L"resetting wimlib compression levels", ret);
261 ret = wimlib_open_wim(INFILE, 0, &in);
263 fatal_wimlib_error(L"opening input WIM with wimlib", ret);
265 if (testspec->level) {
266 ret = wimlib_set_default_compression_level(testspec->ctype,
269 fatal_wimlib_error(L"setting wimlib compression level",
274 ret = wimlib_create_new_wim(testspec->ctype, &out);
276 fatal_wimlib_error(L"creating output WIMStruct", ret);
278 if (testspec->solid) {
279 ret = wimlib_set_output_pack_compression_type(out,
282 fatal_wimlib_error(L"setting wimlib solid compression "
287 if (testspec->chunk_size) {
288 if (testspec->solid) {
289 ret = wimlib_set_output_pack_chunk_size(out,
290 testspec->chunk_size);
292 ret = wimlib_set_output_chunk_size(out,
293 testspec->chunk_size);
296 fatal_wimlib_error(L"setting wimlib output chunk size",
301 ret = wimlib_export_image(in, IN_IMAGE, out, NULL, NULL, 0);
303 fatal_wimlib_error(L"exporting image with wimlib", ret);
305 ret = wimlib_write(out, OUTFILE, WIMLIB_ALL_IMAGES,
306 (testspec->solid ? WIMLIB_WRITE_FLAG_SOLID : 0), 0);
308 fatal_wimlib_error(L"writing output WIM with wimlib", ret);
313 end_test(testspec->description);
317 run_wimgapi_test(const struct wimgapi_test_spec *testspec)
319 HANDLE hInWim, hOutWim;
325 hInWim = WIMCreateFile(INFILE, WIM_GENERIC_READ, WIM_OPEN_EXISTING,
329 fatal_win32_error(L"opening input WIM with WIMGAPI");
331 WIMSetTemporaryPath(hInWim, TMPDIR);
333 hInImage = WIMLoadImage(hInWim, IN_IMAGE);
335 fatal_win32_error(L"loading input image with WIMGAPI");
338 flags |= WIM_FLAG_SOLID;
339 if (testspec->wimboot)
340 flags |= WIM_FLAG_WIM_BOOT;
341 hOutWim = WIMCreateFile(OUTFILE, WIM_GENERIC_WRITE, WIM_CREATE_ALWAYS,
342 flags, testspec->compressionType, NULL);
344 fatal_win32_error(L"opening output WIM with WIMGAPI");
346 WIMSetTemporaryPath(hOutWim, TMPDIR);
348 if (!WIMExportImage(hInImage, hOutWim, 0))
349 fatal_win32_error(L"exporting image with WIMGAPI");
351 WIMCloseHandle(hOutWim);
352 WIMCloseHandle(hInImage);
353 WIMCloseHandle(hInWim);
355 end_test(testspec->description);
359 wmain(int argc, wchar_t *argv[])
361 if (!SetCurrentDirectory(VOLUME))
362 fatal_win32_error(L"changing directory to " VOLUME);
364 for (size_t i = 0; i < ARRAY_LEN(wimlib_test_specs); i++)
365 run_wimlib_test(&wimlib_test_specs[i]);
367 for (size_t i = 0; i < ARRAY_LEN(wimgapi_test_specs); i++)
368 run_wimgapi_test(&wimgapi_test_specs[i]);