VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstCompressionBenchmark.cpp@ 74795

Last change on this file since 74795 was 69111, checked in by vboxsync, 7 years ago

(C) year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.3 KB
Line 
1/* $Id: tstCompressionBenchmark.cpp 69111 2017-10-17 14:26:02Z vboxsync $ */
2/** @file
3 * Compression Benchmark for SSM and PGM.
4 */
5
6/*
7 * Copyright (C) 2009-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <iprt/asm.h>
23#include <iprt/assert.h>
24#include <iprt/buildconfig.h>
25#include <iprt/crc.h>
26#include <iprt/ctype.h>
27#include <iprt/err.h>
28#include <iprt/file.h>
29#include <iprt/getopt.h>
30#include <iprt/initterm.h>
31#include <iprt/md5.h>
32#include <iprt/sha.h>
33#include <iprt/mem.h>
34#include <iprt/param.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <iprt/time.h>
38#include <iprt/zip.h>
39
40
41/*********************************************************************************************************************************
42* Global Variables *
43*********************************************************************************************************************************/
44static size_t g_cPages = 20*_1M / PAGE_SIZE;
45static size_t g_cbPages;
46static uint8_t *g_pabSrc;
47
48/** Buffer for the decompressed data (g_cbPages). */
49static uint8_t *g_pabDecompr;
50
51/** Buffer for the compressed data (g_cbComprAlloc). */
52static uint8_t *g_pabCompr;
53/** The current size of the compressed data, ComprOutCallback */
54static size_t g_cbCompr;
55/** The current offset into the compressed data, DecomprInCallback. */
56static size_t g_offComprIn;
57/** The amount of space allocated for compressed data. */
58static size_t g_cbComprAlloc;
59
60
61/**
62 * Store compressed data in the g_pabCompr buffer.
63 */
64static DECLCALLBACK(int) ComprOutCallback(void *pvUser, const void *pvBuf, size_t cbBuf)
65{
66 NOREF(pvUser);
67 AssertReturn(g_cbCompr + cbBuf <= g_cbComprAlloc, VERR_BUFFER_OVERFLOW);
68 memcpy(&g_pabCompr[g_cbCompr], pvBuf, cbBuf);
69 g_cbCompr += cbBuf;
70 return VINF_SUCCESS;
71}
72
73/**
74 * Read compressed data from g_pabComrp.
75 */
76static DECLCALLBACK(int) DecomprInCallback(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbBuf)
77{
78 NOREF(pvUser);
79 size_t cb = RT_MIN(cbBuf, g_cbCompr - g_offComprIn);
80 if (pcbBuf)
81 *pcbBuf = cb;
82// AssertReturn(cb > 0, VERR_EOF);
83 memcpy(pvBuf, &g_pabCompr[g_offComprIn], cb);
84 g_offComprIn += cb;
85 return VINF_SUCCESS;
86}
87
88
89/**
90 * Benchmark RTCrc routines potentially relevant for SSM or PGM - All in one go.
91 *
92 * @param pabSrc Pointer to the test data.
93 * @param cbSrc The size of the test data.
94 */
95static void tstBenchmarkCRCsAllInOne(uint8_t const *pabSrc, size_t cbSrc)
96{
97 RTPrintf("Algorithm Speed Time Digest\n"
98 "------------------------------------------------------------------------------\n");
99
100 uint64_t NanoTS = RTTimeNanoTS();
101 uint32_t u32Crc = RTCrc32(pabSrc, cbSrc);
102 NanoTS = RTTimeNanoTS() - NanoTS;
103 unsigned uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
104 RTPrintf("CRC-32 %'9u KB/s %'15llu ns - %08x\n", uSpeed, NanoTS, u32Crc);
105
106
107 NanoTS = RTTimeNanoTS();
108 uint64_t u64Crc = RTCrc64(pabSrc, cbSrc);
109 NanoTS = RTTimeNanoTS() - NanoTS;
110 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
111 RTPrintf("CRC-64 %'9u KB/s %'15llu ns - %016llx\n", uSpeed, NanoTS, u64Crc);
112
113 NanoTS = RTTimeNanoTS();
114 u32Crc = RTCrcAdler32(pabSrc, cbSrc);
115 NanoTS = RTTimeNanoTS() - NanoTS;
116 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
117 RTPrintf("Adler-32 %'9u KB/s %'15llu ns - %08x\n", uSpeed, NanoTS, u32Crc);
118
119 NanoTS = RTTimeNanoTS();
120 uint8_t abMd5Hash[RTMD5HASHSIZE];
121 RTMd5(pabSrc, cbSrc, abMd5Hash);
122 NanoTS = RTTimeNanoTS() - NanoTS;
123 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
124 char szDigest[257];
125 RTMd5ToString(abMd5Hash, szDigest, sizeof(szDigest));
126 RTPrintf("MD5 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest);
127
128 NanoTS = RTTimeNanoTS();
129 uint8_t abSha1Hash[RTSHA1_HASH_SIZE];
130 RTSha1(pabSrc, cbSrc, abSha1Hash);
131 NanoTS = RTTimeNanoTS() - NanoTS;
132 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
133 RTSha1ToString(abSha1Hash, szDigest, sizeof(szDigest));
134 RTPrintf("SHA-1 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest);
135
136 NanoTS = RTTimeNanoTS();
137 uint8_t abSha256Hash[RTSHA256_HASH_SIZE];
138 RTSha256(pabSrc, cbSrc, abSha256Hash);
139 NanoTS = RTTimeNanoTS() - NanoTS;
140 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
141 RTSha256ToString(abSha256Hash, szDigest, sizeof(szDigest));
142 RTPrintf("SHA-256 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest);
143
144 NanoTS = RTTimeNanoTS();
145 uint8_t abSha512Hash[RTSHA512_HASH_SIZE];
146 RTSha512(pabSrc, cbSrc, abSha512Hash);
147 NanoTS = RTTimeNanoTS() - NanoTS;
148 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
149 RTSha512ToString(abSha512Hash, szDigest, sizeof(szDigest));
150 RTPrintf("SHA-512 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest);
151}
152
153
154/**
155 * Benchmark RTCrc routines potentially relevant for SSM or PGM - Page by page.
156 *
157 * @param pabSrc Pointer to the test data.
158 * @param cbSrc The size of the test data.
159 */
160static void tstBenchmarkCRCsPageByPage(uint8_t const *pabSrc, size_t cbSrc)
161{
162 RTPrintf("Algorithm Speed Time \n"
163 "----------------------------------------------\n");
164
165 size_t const cPages = cbSrc / PAGE_SIZE;
166
167 uint64_t NanoTS = RTTimeNanoTS();
168 for (uint32_t iPage = 0; iPage < cPages; iPage++)
169 RTCrc32(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE);
170 NanoTS = RTTimeNanoTS() - NanoTS;
171 unsigned uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
172 RTPrintf("CRC-32 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
173
174
175 NanoTS = RTTimeNanoTS();
176 for (uint32_t iPage = 0; iPage < cPages; iPage++)
177 RTCrc64(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE);
178 NanoTS = RTTimeNanoTS() - NanoTS;
179 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
180 RTPrintf("CRC-64 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
181
182 NanoTS = RTTimeNanoTS();
183 for (uint32_t iPage = 0; iPage < cPages; iPage++)
184 RTCrcAdler32(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE);
185 NanoTS = RTTimeNanoTS() - NanoTS;
186 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
187 RTPrintf("Adler-32 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
188
189 NanoTS = RTTimeNanoTS();
190 uint8_t abMd5Hash[RTMD5HASHSIZE];
191 for (uint32_t iPage = 0; iPage < cPages; iPage++)
192 RTMd5(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abMd5Hash);
193 NanoTS = RTTimeNanoTS() - NanoTS;
194 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
195 RTPrintf("MD5 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
196
197 NanoTS = RTTimeNanoTS();
198 uint8_t abSha1Hash[RTSHA1_HASH_SIZE];
199 for (uint32_t iPage = 0; iPage < cPages; iPage++)
200 RTSha1(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abSha1Hash);
201 NanoTS = RTTimeNanoTS() - NanoTS;
202 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
203 RTPrintf("SHA-1 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
204
205 NanoTS = RTTimeNanoTS();
206 uint8_t abSha256Hash[RTSHA256_HASH_SIZE];
207 for (uint32_t iPage = 0; iPage < cPages; iPage++)
208 RTSha256(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abSha256Hash);
209 NanoTS = RTTimeNanoTS() - NanoTS;
210 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
211 RTPrintf("SHA-256 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
212
213 NanoTS = RTTimeNanoTS();
214 uint8_t abSha512Hash[RTSHA512_HASH_SIZE];
215 for (uint32_t iPage = 0; iPage < cPages; iPage++)
216 RTSha512(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abSha512Hash);
217 NanoTS = RTTimeNanoTS() - NanoTS;
218 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
219 RTPrintf("SHA-512 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
220}
221
222
223/** Prints an error message and returns 1 for quick return from main use. */
224static int Error(const char *pszMsgFmt, ...)
225{
226 RTStrmPrintf(g_pStdErr, "\nerror: ");
227 va_list va;
228 va_start(va, pszMsgFmt);
229 RTStrmPrintfV(g_pStdErr, pszMsgFmt, va);
230 va_end(va);
231 return 1;
232}
233
234
235int main(int argc, char **argv)
236{
237 RTR3InitExe(argc, &argv, 0);
238
239 /*
240 * Parse arguments.
241 */
242 static const RTGETOPTDEF s_aOptions[] =
243 {
244 { "--iterations", 'i', RTGETOPT_REQ_UINT32 },
245 { "--num-pages", 'n', RTGETOPT_REQ_UINT32 },
246 { "--page-at-a-time", 'c', RTGETOPT_REQ_UINT32 },
247 { "--page-file", 'f', RTGETOPT_REQ_STRING },
248 { "--offset", 'o', RTGETOPT_REQ_UINT64 },
249 };
250
251 const char *pszPageFile = NULL;
252 uint64_t offPageFile = 0;
253 uint32_t cIterations = 1;
254 uint32_t cPagesAtATime = 1;
255 RTGETOPTUNION Val;
256 RTGETOPTSTATE State;
257 int rc = RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0);
258 AssertRCReturn(rc, 1);
259
260 while ((rc = RTGetOpt(&State, &Val)))
261 {
262 switch (rc)
263 {
264 case 'n':
265 g_cPages = Val.u32;
266 if (g_cPages * PAGE_SIZE * 4 / (PAGE_SIZE * 4) != g_cPages)
267 return Error("The specified page count is too high: %#x (%#llx bytes)\n", g_cPages, (uint64_t)g_cPages * PAGE_SHIFT);
268 if (g_cPages < 1)
269 return Error("The specified page count is too low: %#x\n", g_cPages);
270 break;
271
272 case 'i':
273 cIterations = Val.u32;
274 if (cIterations < 1)
275 return Error("The number of iterations must be 1 or higher\n");
276 break;
277
278 case 'c':
279 cPagesAtATime = Val.u32;
280 if (cPagesAtATime < 1 || cPagesAtATime > 10240)
281 return Error("The specified pages-at-a-time count is out of range: %#x\n", cPagesAtATime);
282 break;
283
284 case 'f':
285 pszPageFile = Val.psz;
286 break;
287
288 case 'o':
289 offPageFile = Val.u64;
290 break;
291
292 case 'O':
293 offPageFile = Val.u64 * PAGE_SIZE;
294 break;
295
296 case 'h':
297 RTPrintf("syntax: tstCompressionBenchmark [options]\n"
298 "\n"
299 "Options:\n"
300 " -h, --help\n"
301 " Show this help page\n"
302 " -i, --iterations <num>\n"
303 " The number of iterations.\n"
304 " -n, --num-pages <pages>\n"
305 " The number of pages.\n"
306 " -c, --pages-at-a-time <pages>\n"
307 " Number of pages at a time.\n"
308 " -f, --page-file <filename>\n"
309 " File or device to read the page from. The default\n"
310 " is to generate some garbage.\n"
311 " -o, --offset <file-offset>\n"
312 " Offset into the page file to start reading at.\n");
313 return 0;
314
315 case 'V':
316 RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
317 return 0;
318
319 default:
320 return RTGetOptPrintError(rc, &Val);
321 }
322 }
323
324 g_cbPages = g_cPages * PAGE_SIZE;
325 uint64_t cbTotal = (uint64_t)g_cPages * PAGE_SIZE * cIterations;
326 uint64_t cbTotalKB = cbTotal / _1K;
327 if (cbTotal / cIterations != g_cbPages)
328 return Error("cPages * cIterations -> overflow\n");
329
330 /*
331 * Gather the test memory.
332 */
333 if (pszPageFile)
334 {
335 size_t cbFile;
336 rc = RTFileReadAllEx(pszPageFile, offPageFile, g_cbPages, RTFILE_RDALL_O_DENY_NONE, (void **)&g_pabSrc, &cbFile);
337 if (RT_FAILURE(rc))
338 return Error("Error reading %zu bytes from %s at %llu: %Rrc\n", g_cbPages, pszPageFile, offPageFile, rc);
339 if (cbFile != g_cbPages)
340 return Error("Error reading %zu bytes from %s at %llu: got %zu bytes\n", g_cbPages, pszPageFile, offPageFile, cbFile);
341 }
342 else
343 {
344 g_pabSrc = (uint8_t *)RTMemAlloc(g_cbPages);
345 if (g_pabSrc)
346 {
347 /* Just fill it with something - warn about the low quality of the something. */
348 RTPrintf("tstCompressionBenchmark: WARNING! No input file was specified so the source\n"
349 "buffer will be filled with generated data of questionable quality.\n");
350#ifdef RT_OS_LINUX
351 RTPrintf("To get real RAM on linux: sudo dd if=/dev/mem ... \n");
352#endif
353 uint8_t *pb = g_pabSrc;
354 uint8_t *pbEnd = &g_pabSrc[g_cbPages];
355 for (; pb != pbEnd; pb += 16)
356 {
357 char szTmp[17];
358 RTStrPrintf(szTmp, sizeof(szTmp), "aaaa%08Xzzzz", (uint32_t)(uintptr_t)pb);
359 memcpy(pb, szTmp, 16);
360 }
361 }
362 }
363
364 g_pabDecompr = (uint8_t *)RTMemAlloc(g_cbPages);
365 g_cbComprAlloc = RT_MAX(g_cbPages * 2, 256 * PAGE_SIZE);
366 g_pabCompr = (uint8_t *)RTMemAlloc(g_cbComprAlloc);
367 if (!g_pabSrc || !g_pabDecompr || !g_pabCompr)
368 return Error("failed to allocate memory buffers (g_cPages=%#x)\n", g_cPages);
369
370 /*
371 * Double loop compressing and uncompressing the data, where the outer does
372 * the specified number of iterations while the inner applies the different
373 * compression algorithms.
374 */
375 struct
376 {
377 /** The time spent decompressing. */
378 uint64_t cNanoDecompr;
379 /** The time spent compressing. */
380 uint64_t cNanoCompr;
381 /** The size of the compressed data. */
382 uint64_t cbCompr;
383 /** First error. */
384 int rc;
385 /** The compression style: block or stream. */
386 bool fBlock;
387 /** Compression type. */
388 RTZIPTYPE enmType;
389 /** Compression level. */
390 RTZIPLEVEL enmLevel;
391 /** Method name. */
392 const char *pszName;
393 } aTests[] =
394 {
395 { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_STORE, RTZIPLEVEL_DEFAULT, "RTZip/Store" },
396 { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_LZF, RTZIPLEVEL_DEFAULT, "RTZip/LZF" },
397/* { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT, "RTZip/zlib" }, - slow plus it randomly hits VERR_GENERAL_FAILURE atm. */
398 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_STORE, RTZIPLEVEL_DEFAULT, "RTZipBlock/Store" },
399 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZF, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZF" },
400 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZJB, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZJB" },
401 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZO, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZO" },
402 };
403 RTPrintf("tstCompressionBenchmark: TESTING..");
404 for (uint32_t i = 0; i < cIterations; i++)
405 {
406 for (uint32_t j = 0; j < RT_ELEMENTS(aTests); j++)
407 {
408 if (RT_FAILURE(aTests[j].rc))
409 continue;
410 memset(g_pabCompr, 0xaa, g_cbComprAlloc);
411 memset(g_pabDecompr, 0xcc, g_cbPages);
412 g_cbCompr = 0;
413 g_offComprIn = 0;
414 RTPrintf("."); RTStrmFlush(g_pStdOut);
415
416 /*
417 * Compress it.
418 */
419 uint64_t NanoTS = RTTimeNanoTS();
420 if (aTests[j].fBlock)
421 {
422 size_t cbLeft = g_cbComprAlloc;
423 uint8_t const *pbSrcPage = g_pabSrc;
424 uint8_t *pbDstPage = g_pabCompr;
425 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
426 {
427 AssertBreakStmt(cbLeft > PAGE_SIZE * 4, aTests[j].rc = rc = VERR_BUFFER_OVERFLOW);
428 uint32_t *pcb = (uint32_t *)pbDstPage;
429 pbDstPage += sizeof(uint32_t);
430 cbLeft -= sizeof(uint32_t);
431 size_t cbSrc = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
432 size_t cbDst;
433 rc = RTZipBlockCompress(aTests[j].enmType, aTests[j].enmLevel, 0 /*fFlags*/,
434 pbSrcPage, cbSrc,
435 pbDstPage, cbLeft, &cbDst);
436 if (RT_FAILURE(rc))
437 {
438 Error("RTZipBlockCompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
439 aTests[j].rc = rc;
440 break;
441 }
442 *pcb = (uint32_t)cbDst;
443 cbLeft -= cbDst;
444 pbDstPage += cbDst;
445 pbSrcPage += cbSrc;
446 }
447 if (RT_FAILURE(rc))
448 continue;
449 g_cbCompr = pbDstPage - g_pabCompr;
450 }
451 else
452 {
453 PRTZIPCOMP pZipComp;
454 rc = RTZipCompCreate(&pZipComp, NULL, ComprOutCallback, aTests[j].enmType, aTests[j].enmLevel);
455 if (RT_FAILURE(rc))
456 {
457 Error("Failed to create the compressor for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
458 aTests[j].rc = rc;
459 continue;
460 }
461
462 uint8_t const *pbSrcPage = g_pabSrc;
463 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
464 {
465 size_t cb = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
466 rc = RTZipCompress(pZipComp, pbSrcPage, cb);
467 if (RT_FAILURE(rc))
468 {
469 Error("RTZipCompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
470 aTests[j].rc = rc;
471 break;
472 }
473 pbSrcPage += cb;
474 }
475 if (RT_FAILURE(rc))
476 continue;
477 rc = RTZipCompFinish(pZipComp);
478 if (RT_FAILURE(rc))
479 {
480 Error("RTZipCompFinish failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
481 aTests[j].rc = rc;
482 break;
483 }
484 RTZipCompDestroy(pZipComp);
485 }
486 NanoTS = RTTimeNanoTS() - NanoTS;
487 aTests[j].cbCompr += g_cbCompr;
488 aTests[j].cNanoCompr += NanoTS;
489
490 /*
491 * Decompress it.
492 */
493 NanoTS = RTTimeNanoTS();
494 if (aTests[j].fBlock)
495 {
496 uint8_t const *pbSrcPage = g_pabCompr;
497 size_t cbLeft = g_cbCompr;
498 uint8_t *pbDstPage = g_pabDecompr;
499 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
500 {
501 size_t cbDst = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
502 size_t cbSrc = *(uint32_t *)pbSrcPage;
503 pbSrcPage += sizeof(uint32_t);
504 cbLeft -= sizeof(uint32_t);
505 rc = RTZipBlockDecompress(aTests[j].enmType, 0 /*fFlags*/,
506 pbSrcPage, cbSrc, &cbSrc,
507 pbDstPage, cbDst, &cbDst);
508 if (RT_FAILURE(rc))
509 {
510 Error("RTZipBlockDecompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
511 aTests[j].rc = rc;
512 break;
513 }
514 pbDstPage += cbDst;
515 cbLeft -= cbSrc;
516 pbSrcPage += cbSrc;
517 }
518 if (RT_FAILURE(rc))
519 continue;
520 }
521 else
522 {
523 PRTZIPDECOMP pZipDecomp;
524 rc = RTZipDecompCreate(&pZipDecomp, NULL, DecomprInCallback);
525 if (RT_FAILURE(rc))
526 {
527 Error("Failed to create the decompressor for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
528 aTests[j].rc = rc;
529 continue;
530 }
531
532 uint8_t *pbDstPage = g_pabDecompr;
533 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
534 {
535 size_t cb = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
536 rc = RTZipDecompress(pZipDecomp, pbDstPage, cb, NULL);
537 if (RT_FAILURE(rc))
538 {
539 Error("RTZipDecompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
540 aTests[j].rc = rc;
541 break;
542 }
543 pbDstPage += cb;
544 }
545 RTZipDecompDestroy(pZipDecomp);
546 if (RT_FAILURE(rc))
547 continue;
548 }
549 NanoTS = RTTimeNanoTS() - NanoTS;
550 aTests[j].cNanoDecompr += NanoTS;
551
552 if (memcmp(g_pabDecompr, g_pabSrc, g_cbPages))
553 {
554 Error("The compressed data doesn't match the source for '%s' (%#u)\n", aTests[j].pszName, j);
555 aTests[j].rc = VERR_BAD_EXE_FORMAT;
556 continue;
557 }
558 }
559 }
560 if (RT_SUCCESS(rc))
561 RTPrintf("\n");
562
563 /*
564 * Report the results.
565 */
566 rc = 0;
567 RTPrintf("tstCompressionBenchmark: BEGIN RESULTS\n");
568 RTPrintf("%-20s Compression Decompression\n", "");
569 RTPrintf("%-20s In Out Ratio Size In Out\n", "Method");
570 RTPrintf("%.20s-----------------------------------------------------------------------------------------\n", "---------------------------------------------");
571 for (uint32_t j = 0; j < RT_ELEMENTS(aTests); j++)
572 {
573 if (RT_SUCCESS(aTests[j].rc))
574 {
575 unsigned uComprSpeedIn = (unsigned)(cbTotalKB / (long double)aTests[j].cNanoCompr * 1000000000.0);
576 unsigned uComprSpeedOut = (unsigned)(aTests[j].cbCompr / (long double)aTests[j].cNanoCompr * 1000000000.0 / 1024);
577 unsigned uRatio = (unsigned)(aTests[j].cbCompr / cIterations * 100 / g_cbPages);
578 unsigned uDecomprSpeedIn = (unsigned)(aTests[j].cbCompr / (long double)aTests[j].cNanoDecompr * 1000000000.0 / 1024);
579 unsigned uDecomprSpeedOut = (unsigned)(cbTotalKB / (long double)aTests[j].cNanoDecompr * 1000000000.0);
580 RTPrintf("%-20s %'9u KB/s %'9u KB/s %3u%% %'11llu bytes %'9u KB/s %'9u KB/s",
581 aTests[j].pszName,
582 uComprSpeedIn, uComprSpeedOut, uRatio, aTests[j].cbCompr / cIterations,
583 uDecomprSpeedIn, uDecomprSpeedOut);
584#if 0
585 RTPrintf(" [%'14llu / %'14llu ns]\n",
586 aTests[j].cNanoCompr / cIterations,
587 aTests[j].cNanoDecompr / cIterations);
588#else
589 RTPrintf("\n");
590#endif
591 }
592 else
593 {
594 RTPrintf("%-20s: %Rrc\n", aTests[j].pszName, aTests[j].rc);
595 rc = 1;
596 }
597 }
598 if (pszPageFile)
599 RTPrintf("Input: %'10zu pages from '%s' starting at offset %'lld (%#llx)\n"
600 " %'11zu bytes\n",
601 g_cPages, pszPageFile, offPageFile, offPageFile, g_cbPages);
602 else
603 RTPrintf("Input: %'10zu pages of generated rubbish %'11zu bytes\n",
604 g_cPages, g_cbPages);
605
606 /*
607 * Count zero pages in the data set.
608 */
609 size_t cZeroPages = 0;
610 for (size_t iPage = 0; iPage < g_cPages; iPage++)
611 {
612 if (ASMMemIsZeroPage(&g_pabSrc[iPage * PAGE_SIZE]))
613 cZeroPages++;
614 }
615 RTPrintf(" %'10zu zero pages (%u %%)\n", cZeroPages, cZeroPages * 100 / g_cPages);
616
617 /*
618 * A little extension to the test, benchmark relevant CRCs.
619 */
620 RTPrintf("\n"
621 "tstCompressionBenchmark: Hash/CRC - All In One\n");
622 tstBenchmarkCRCsAllInOne(g_pabSrc, g_cbPages);
623
624 RTPrintf("\n"
625 "tstCompressionBenchmark: Hash/CRC - Page by Page\n");
626 tstBenchmarkCRCsPageByPage(g_pabSrc, g_cbPages);
627
628 RTPrintf("\n"
629 "tstCompressionBenchmark: Hash/CRC - Zero Page Digest\n");
630 static uint8_t s_abZeroPg[PAGE_SIZE];
631 RT_ZERO(s_abZeroPg);
632 tstBenchmarkCRCsAllInOne(s_abZeroPg, PAGE_SIZE);
633
634 RTPrintf("\n"
635 "tstCompressionBenchmark: Hash/CRC - Zero Half Page Digest\n");
636 tstBenchmarkCRCsAllInOne(s_abZeroPg, PAGE_SIZE / 2);
637
638 RTPrintf("tstCompressionBenchmark: END RESULTS\n");
639
640 return rc;
641}
642
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use