VirtualBox

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

Last change on this file since 93582 was 93554, checked in by vboxsync, 3 years ago

VMM: Changed PAGE_SIZE -> GUEST_PAGE_SIZE / HOST_PAGE_SIZE, PAGE_SHIFT -> GUEST_PAGE_SHIFT / HOST_PAGE_SHIFT, and PAGE_OFFSET_MASK -> GUEST_PAGE_OFFSET_MASK / HOST_PAGE_OFFSET_MASK. Also removed most usage of ASMMemIsZeroPage and ASMMemZeroPage since the host and guest page size doesn't need to be the same any more. Some work left to do in the page pool code. bugref:9898

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