VirtualBox

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

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

PGMSavedState: MMIO2 optimizations in the works.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.6 KB
Line 
1/* $Id: tstCompressionBenchmark.cpp 23513 2009-10-02 13:21:27Z 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/**
156 * Benchmark RTCrc routines potentially relevant for SSM or PGM - Page by page.
157 *
158 * @param pabSrc Pointer to the test data.
159 * @param cbSrc The size of the test data.
160 */
161static void tstBenchmarkCRCsPageByPage(uint8_t const *pabSrc, size_t cbSrc)
162{
163 RTPrintf("Algorithm Speed Time \n"
164 "----------------------------------------------\n");
165
166 size_t const cPages = cbSrc / PAGE_SIZE;
167
168 uint64_t NanoTS = RTTimeNanoTS();
169 for (uint32_t iPage = 0; iPage < cPages; iPage++)
170 RTCrc32(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE);
171 NanoTS = RTTimeNanoTS() - NanoTS;
172 unsigned uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
173 RTPrintf("CRC-32 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
174
175
176 NanoTS = RTTimeNanoTS();
177 for (uint32_t iPage = 0; iPage < cPages; iPage++)
178 RTCrc64(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE);
179 NanoTS = RTTimeNanoTS() - NanoTS;
180 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
181 RTPrintf("CRC-64 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
182
183 NanoTS = RTTimeNanoTS();
184 for (uint32_t iPage = 0; iPage < cPages; iPage++)
185 RTCrcAdler32(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE);
186 NanoTS = RTTimeNanoTS() - NanoTS;
187 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
188 RTPrintf("Adler-32 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
189
190 NanoTS = RTTimeNanoTS();
191 uint8_t abMd5Hash[RTMD5HASHSIZE];
192 for (uint32_t iPage = 0; iPage < cPages; iPage++)
193 RTMd5(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abMd5Hash);
194 NanoTS = RTTimeNanoTS() - NanoTS;
195 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
196 RTPrintf("MD5 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
197
198 NanoTS = RTTimeNanoTS();
199 uint8_t abSha1Hash[RTSHA1_HASH_SIZE];
200 for (uint32_t iPage = 0; iPage < cPages; iPage++)
201 RTSha1(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abSha1Hash);
202 NanoTS = RTTimeNanoTS() - NanoTS;
203 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
204 RTPrintf("SHA-1 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
205
206 NanoTS = RTTimeNanoTS();
207 uint8_t abSha256Hash[RTSHA256_HASH_SIZE];
208 for (uint32_t iPage = 0; iPage < cPages; iPage++)
209 RTSha256(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abSha256Hash);
210 NanoTS = RTTimeNanoTS() - NanoTS;
211 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
212 RTPrintf("SHA-256 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
213
214 NanoTS = RTTimeNanoTS();
215 uint8_t abSha512Hash[RTSHA512_HASH_SIZE];
216 for (uint32_t iPage = 0; iPage < cPages; iPage++)
217 RTSha512(&pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, abSha512Hash);
218 NanoTS = RTTimeNanoTS() - NanoTS;
219 uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024);
220 RTPrintf("SHA-512 %'9u KB/s %'15llu ns\n", uSpeed, NanoTS);
221}
222
223
224/** Prints an error message and returns 1 for quick return from main use. */
225static int Error(const char *pszMsgFmt, ...)
226{
227 RTStrmPrintf(g_pStdErr, "\nerror: ");
228 va_list va;
229 va_start(va, pszMsgFmt);
230 RTStrmPrintfV(g_pStdErr, pszMsgFmt, va);
231 va_end(va);
232 return 1;
233}
234
235
236int main(int argc, char **argv)
237{
238 RTR3Init();
239
240 /*
241 * Parse arguments.
242 */
243 static const RTGETOPTDEF s_aOptions[] =
244 {
245 { "--interations", 'i', RTGETOPT_REQ_UINT32 },
246 { "--num-pages", 'n', RTGETOPT_REQ_UINT32 },
247 { "--page-at-a-time", 'c', RTGETOPT_REQ_UINT32 },
248 { "--page-file", 'f', RTGETOPT_REQ_STRING },
249 { "--offset", 'o', RTGETOPT_REQ_UINT64 },
250 { "--help", 'h', RTGETOPT_REQ_NOTHING },
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 default:
318 if (rc == VINF_GETOPT_NOT_OPTION)
319 Error("unknown argument: %s\n", Val.psz);
320 else if (rc > 0)
321 {
322 if (RT_C_IS_GRAPH(rc))
323 Error("unhandled option: -%c\n", rc);
324 else
325 Error("unhandled option: %d\n", rc);
326 }
327 else if (rc == VERR_GETOPT_UNKNOWN_OPTION)
328 Error("unknown option: %s\n", Val.psz);
329 else if (Val.pDef)
330 Error("%s: %Rrs\n", Val.pDef->pszLong, rc);
331 else
332 Error("%Rrs\n", rc);
333 return 1;
334 }
335 }
336
337 g_cbPages = g_cPages * PAGE_SIZE;
338 uint64_t cbTotal = (uint64_t)g_cPages * PAGE_SIZE * cIterations;
339 uint64_t cbTotalKB = cbTotal / _1K;
340 if (cbTotal / cIterations != g_cbPages)
341 return Error("cPages * cIterations -> overflow\n");
342
343 /*
344 * Gather the test memory.
345 */
346 if (pszPageFile)
347 {
348 size_t cbFile;
349 rc = RTFileReadAllEx(pszPageFile, offPageFile, g_cbPages, RTFILE_RDALL_O_DENY_NONE, (void **)&g_pabSrc, &cbFile);
350 if (RT_FAILURE(rc))
351 return Error("Error reading %zu bytes from %s at %llu: %Rrc\n", g_cbPages, pszPageFile, offPageFile, rc);
352 if (cbFile != g_cbPages)
353 return Error("Error reading %zu bytes from %s at %llu: got %zu bytes\n", g_cbPages, pszPageFile, offPageFile, cbFile);
354 }
355 else
356 {
357 g_pabSrc = (uint8_t *)RTMemAlloc(g_cbPages);
358 if (g_pabSrc)
359 {
360 /* Just fill it with something - warn about the low quality of the something. */
361 RTPrintf("tstCompressionBenchmark: WARNING! No input file was specified so the source\n"
362 "buffer will be filled with generated data of questionable quality.\n");
363#ifdef RT_OS_LINUX
364 RTPrintf("To get real RAM on linux: sudo dd if=/dev/mem ... \n");
365#endif
366 uint8_t *pb = g_pabSrc;
367 uint8_t *pbEnd = &g_pabSrc[g_cbPages];
368 for (; pb != pbEnd; pb += 16)
369 {
370 char szTmp[17];
371 RTStrPrintf(szTmp, sizeof(szTmp), "aaaa%08Xzzzz", (uint32_t)(uintptr_t)pb);
372 memcpy(pb, szTmp, 16);
373 }
374 }
375 }
376
377 g_pabDecompr = (uint8_t *)RTMemAlloc(g_cbPages);
378 g_cbComprAlloc = RT_MAX(g_cbPages * 2, 256 * PAGE_SIZE);
379 g_pabCompr = (uint8_t *)RTMemAlloc(g_cbComprAlloc);
380 if (!g_pabSrc || !g_pabDecompr || !g_pabCompr)
381 return Error("failed to allocate memory buffers (g_cPages=%#x)\n", g_cPages);
382
383 /*
384 * Double loop compressing and uncompressing the data, where the outer does
385 * the specified number of interations while the inner applies the different
386 * compression algorithms.
387 */
388 struct
389 {
390 /** The time spent decompressing. */
391 uint64_t cNanoDecompr;
392 /** The time spent compressing. */
393 uint64_t cNanoCompr;
394 /** The size of the compressed data. */
395 uint64_t cbCompr;
396 /** First error. */
397 int rc;
398 /** The compression style: block or stream. */
399 bool fBlock;
400 /** Compresstion type. */
401 RTZIPTYPE enmType;
402 /** Compresison level. */
403 RTZIPLEVEL enmLevel;
404 /** Method name. */
405 const char *pszName;
406 } aTests[] =
407 {
408 { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_STORE, RTZIPLEVEL_DEFAULT, "RTZip/Store" },
409 { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_LZF, RTZIPLEVEL_DEFAULT, "RTZip/LZF" },
410/* { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT, "RTZip/zlib" }, - slow plus it randomly hits VERR_GENERAL_FAILURE atm. */
411 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_STORE, RTZIPLEVEL_DEFAULT, "RTZipBlock/Store" },
412 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZF, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZF" },
413 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZJB, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZJB" },
414 { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZO, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZO" },
415 };
416 RTPrintf("tstCompressionBenchmark: TESTING..");
417 for (uint32_t i = 0; i < cIterations; i++)
418 {
419 for (uint32_t j = 0; j < RT_ELEMENTS(aTests); j++)
420 {
421 if (RT_FAILURE(aTests[j].rc))
422 continue;
423 memset(g_pabCompr, 0xaa, g_cbComprAlloc);
424 memset(g_pabDecompr, 0xcc, g_cbPages);
425 g_cbCompr = 0;
426 g_offComprIn = 0;
427 RTPrintf("."); RTStrmFlush(g_pStdOut);
428
429 /*
430 * Compress it.
431 */
432 uint64_t NanoTS = RTTimeNanoTS();
433 if (aTests[j].fBlock)
434 {
435 size_t cbLeft = g_cbComprAlloc;
436 uint8_t const *pbSrcPage = g_pabSrc;
437 uint8_t *pbDstPage = g_pabCompr;
438 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
439 {
440 AssertBreakStmt(cbLeft > PAGE_SIZE * 4, aTests[j].rc = rc = VERR_BUFFER_OVERFLOW);
441 uint32_t *pcb = (uint32_t *)pbDstPage;
442 pbDstPage += sizeof(uint32_t);
443 cbLeft -= sizeof(uint32_t);
444 size_t cbSrc = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
445 size_t cbDst;
446 rc = RTZipBlockCompress(aTests[j].enmType, aTests[j].enmLevel, 0 /*fFlags*/,
447 pbSrcPage, cbSrc,
448 pbDstPage, cbLeft, &cbDst);
449 if (RT_FAILURE(rc))
450 {
451 Error("RTZipBlockCompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
452 aTests[j].rc = rc;
453 break;
454 }
455 *pcb = (uint32_t)cbDst;
456 cbLeft -= cbDst;
457 pbDstPage += cbDst;
458 pbSrcPage += cbSrc;
459 }
460 if (RT_FAILURE(rc))
461 continue;
462 g_cbCompr = pbDstPage - g_pabCompr;
463 }
464 else
465 {
466 PRTZIPCOMP pZipComp;
467 rc = RTZipCompCreate(&pZipComp, NULL, ComprOutCallback, aTests[j].enmType, aTests[j].enmLevel);
468 if (RT_FAILURE(rc))
469 {
470 Error("Failed to create the compressor for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
471 aTests[j].rc = rc;
472 continue;
473 }
474
475 uint8_t const *pbSrcPage = g_pabSrc;
476 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
477 {
478 size_t cb = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
479 rc = RTZipCompress(pZipComp, pbSrcPage, cb);
480 if (RT_FAILURE(rc))
481 {
482 Error("RTZipCompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
483 aTests[j].rc = rc;
484 break;
485 }
486 pbSrcPage += cb;
487 }
488 if (RT_FAILURE(rc))
489 continue;
490 rc = RTZipCompFinish(pZipComp);
491 if (RT_FAILURE(rc))
492 {
493 Error("RTZipCompFinish failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
494 aTests[j].rc = rc;
495 break;
496 }
497 RTZipCompDestroy(pZipComp);
498 }
499 NanoTS = RTTimeNanoTS() - NanoTS;
500 aTests[j].cbCompr += g_cbCompr;
501 aTests[j].cNanoCompr += NanoTS;
502
503 /*
504 * Decompress it.
505 */
506 NanoTS = RTTimeNanoTS();
507 if (aTests[j].fBlock)
508 {
509 uint8_t const *pbSrcPage = g_pabCompr;
510 size_t cbLeft = g_cbCompr;
511 uint8_t *pbDstPage = g_pabDecompr;
512 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
513 {
514 size_t cbDst = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
515 size_t cbSrc = *(uint32_t *)pbSrcPage;
516 pbSrcPage += sizeof(uint32_t);
517 cbLeft -= sizeof(uint32_t);
518 rc = RTZipBlockDecompress(aTests[j].enmType, 0 /*fFlags*/,
519 pbSrcPage, cbSrc, &cbSrc,
520 pbDstPage, cbDst, &cbDst);
521 if (RT_FAILURE(rc))
522 {
523 Error("RTZipBlockDecompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
524 aTests[j].rc = rc;
525 break;
526 }
527 pbDstPage += cbDst;
528 cbLeft -= cbSrc;
529 pbSrcPage += cbSrc;
530 }
531 if (RT_FAILURE(rc))
532 continue;
533 }
534 else
535 {
536 PRTZIPDECOMP pZipDecomp;
537 rc = RTZipDecompCreate(&pZipDecomp, NULL, DecomprInCallback);
538 if (RT_FAILURE(rc))
539 {
540 Error("Failed to create the decompressor for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
541 aTests[j].rc = rc;
542 continue;
543 }
544
545 uint8_t *pbDstPage = g_pabDecompr;
546 for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime)
547 {
548 size_t cb = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE;
549 rc = RTZipDecompress(pZipDecomp, pbDstPage, cb, NULL);
550 if (RT_FAILURE(rc))
551 {
552 Error("RTZipDecompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc);
553 aTests[j].rc = rc;
554 break;
555 }
556 pbDstPage += cb;
557 }
558 RTZipDecompDestroy(pZipDecomp);
559 if (RT_FAILURE(rc))
560 continue;
561 }
562 NanoTS = RTTimeNanoTS() - NanoTS;
563 aTests[j].cNanoDecompr += NanoTS;
564
565 if (memcmp(g_pabDecompr, g_pabSrc, g_cbPages))
566 {
567 Error("The compressed data doesn't match the source for '%s' (%#u)\n", aTests[j].pszName, j);
568 aTests[j].rc = VERR_BAD_EXE_FORMAT;
569 continue;
570 }
571 }
572 }
573 if (RT_SUCCESS(rc))
574 RTPrintf("\n");
575
576 /*
577 * Report the results.
578 */
579 rc = 0;
580 RTPrintf("tstCompressionBenchmark: BEGIN RESULTS\n");
581 RTPrintf("%-20s Compression Decompression\n", "");
582 RTPrintf("%-20s In Out Ratio Size In Out\n", "Method");
583 RTPrintf("%.20s-----------------------------------------------------------------------------------------\n", "---------------------------------------------");
584 for (uint32_t j = 0; j < RT_ELEMENTS(aTests); j++)
585 {
586 if (RT_SUCCESS(aTests[j].rc))
587 {
588 unsigned uComprSpeedIn = (unsigned)(cbTotalKB / (long double)aTests[j].cNanoCompr * 1000000000.0);
589 unsigned uComprSpeedOut = (unsigned)(aTests[j].cbCompr / (long double)aTests[j].cNanoCompr * 1000000000.0 / 1024);
590 unsigned uRatio = (unsigned)(aTests[j].cbCompr / cIterations * 100 / g_cbPages);
591 unsigned uDecomprSpeedIn = (unsigned)(aTests[j].cbCompr / (long double)aTests[j].cNanoDecompr * 1000000000.0 / 1024);
592 unsigned uDecomprSpeedOut = (unsigned)(cbTotalKB / (long double)aTests[j].cNanoDecompr * 1000000000.0);
593 RTPrintf("%-20s %'9u KB/s %'9u KB/s %3u%% %'11llu bytes %'9u KB/s %'9u KB/s",
594 aTests[j].pszName,
595 uComprSpeedIn, uComprSpeedOut, uRatio, aTests[j].cbCompr / cIterations,
596 uDecomprSpeedIn, uDecomprSpeedOut);
597#if 0
598 RTPrintf(" [%'14llu / %'14llu ns]\n",
599 aTests[j].cNanoCompr / cIterations,
600 aTests[j].cNanoDecompr / cIterations);
601#else
602 RTPrintf("\n");
603#endif
604 }
605 else
606 {
607 RTPrintf("%-20s: %Rrc\n", aTests[j].pszName, aTests[j].rc);
608 rc = 1;
609 }
610 }
611 if (pszPageFile)
612 RTPrintf("Input: %'10zu pages from '%s' starting at offset %'lld (%#llx)\n"
613 " %'11zu bytes\n",
614 g_cPages, pszPageFile, offPageFile, offPageFile, g_cbPages);
615 else
616 RTPrintf("Input: %'10zu pages of generated rubbish %'11zu bytes\n",
617 g_cPages, g_cbPages);
618
619 /*
620 * Count zero pages in the data set.
621 */
622 size_t cZeroPages = 0;
623 for (size_t iPage = 0; iPage < g_cPages; iPage++)
624 {
625 if (!ASMMemIsAllU32(&g_pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, 0))
626 cZeroPages++;
627 }
628 RTPrintf(" %'10zu zero pages (%u %%)\n", cZeroPages, cZeroPages * 100 / g_cPages);
629
630 /*
631 * A little extension to the test, benchmark relevant CRCs.
632 */
633 RTPrintf("\n"
634 "tstCompressionBenchmark: Hash/CRC - All In One\n");
635 tstBenchmarkCRCsAllInOne(g_pabSrc, g_cbPages);
636
637 RTPrintf("\n"
638 "tstCompressionBenchmark: Hash/CRC - Page by Page\n");
639 tstBenchmarkCRCsPageByPage(g_pabSrc, g_cbPages);
640
641 RTPrintf("\n"
642 "tstCompressionBenchmark: Hash/CRC - Zero Page Digest\n");
643 static uint8_t s_abZeroPg[PAGE_SIZE];
644 RT_ZERO(s_abZeroPg);
645 tstBenchmarkCRCsAllInOne(s_abZeroPg, PAGE_SIZE);
646
647 RTPrintf("\n"
648 "tstCompressionBenchmark: Hash/CRC - Zero Half Page Digest\n");
649 tstBenchmarkCRCsAllInOne(s_abZeroPg, PAGE_SIZE / 2);
650
651 RTPrintf("tstCompressionBenchmark: END RESULTS\n");
652
653 return rc;
654}
655
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