VirtualBox

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

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

tstCompressionBenchmark: Page by page CRC/Hash benchmarking.

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