VirtualBox

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

Last change on this file since 26871 was 26517, checked in by vboxsync, 15 years ago

*: RTGetOpt cleanup related to --help and --version (now standard option). Use RTGetOptPrintError.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette