VirtualBox

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

Last change on this file since 28867 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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