1 module test_xxh32;
2 
3 /** MD5 Checksum Routines Unittest (D module) */
4 import core.stdc.stdlib;
5 import std.datetime.stopwatch;
6 import std.digest;
7 version (UseXXHSourceFromDub) import xxhash3;
8 version (UseXXHSourceFromLocalDir) import local_dev.xxh;
9 version (UseXXHSourceFromPhobos) import std.digest.xxh;
10 import std.file;
11 import std.format;
12 import std.range;
13 import std.stdint;
14 import std.stdio;
15 
16 import test_helpers;
17 import test_csv;
18 
19 /** Test and benchmark the XXH32 functions */
20 
21 int test_xxh32(int argTimeLimit, bool writeCSV) {
22 	auto csvFileName = "./docs/benchmark_xxh32.csv";
23 	auto csvFile = new TestCSVFile!XXH32TestData(csvFileName);
24 
25 	auto timeLimitSW = StopWatch(AutoStart.yes);
26 	auto sw = StopWatch(AutoStart.no);
27 	const int rc = 0;
28 	float mbs_average = 0.0;
29 	int mbs_counts = 0;
30 
31 	foreach (int size; 4 .. 16) {
32 		stdout.flush(); // Flush contents of stdout to avoid half done outputs in CI Pipeline
33 		if (timeLimitSW.peek.total!"seconds" > argTimeLimit) {
34 			writeln("Time Limit execeeded, Abort test.");
35 			break;
36 		}
37 		foreach (ubyte i; 0 .. (256 / 32)) {
38 			int tsize = 2 ^^ 20 * size;
39 			auto test = new ubyte[tsize];
40 			test[] = cast(ubyte)(i * 32);
41 
42 			/* Test 1 */
43 			XXH32_canonical_t hash1;
44 			{
45 				XXH_32 xxh;
46 				sw.reset;
47 				sw.start;
48 				xxh.start(); // Create a state
49 				for (int j = 0; j < tsize; j += tsize / 8) {
50 					xxh.put(test[j .. j + tsize / 8]); // Hash the file in chunks
51 				}
52 				hash1 = xxh.finish(); // Finalize the hash
53 				sw.stop;
54 			}
55 			auto time1 = sw.peek;
56 
57 			/* Test 2 */
58 			XXH32_canonical_t hash3;
59 			{
60 				auto xxh = new XXH32Digest();
61 				sw.reset;
62 				sw.start;
63 				hash3 = xxh.digest(test); //&test[0], tsize, 0xbaad5eed);
64 				sw.stop;
65 			}
66 			auto time2 = sw.peek;
67 			mbs_average += getMegaBytePerSeconds(tsize, time2);
68 			mbs_counts++;
69 
70 			/* Status output */
71 			version (unittest) {
72 			} else {
73 				import app : argVerbose;
74 
75 				if (argVerbose)
76 					writefln("Input: size=0x%08x fill=0x%02x, hash %s, %8fs, %8fs, %10.6f MB/s, %10.6f MB/s",
77 						tsize, i, hash1.toHexString,
78 						getFloatSecond(time1), getFloatSecond(time2),
79 						getMegaBytePerSeconds(tsize, time1), getMegaBytePerSeconds(tsize, time2));
80 			}
81 			/* Prepare CSV output */
82 			auto testCsv = XXH32TestData(tsize, i, hash3, time1, time2);
83 			csvFile.addEntry(testCsv);
84 
85 			/* Check hash results */
86 			assert(hash1 == hash3, "Hashes mismatch");
87 		}
88 	}
89 	timeLimitSW.stop;
90 
91 	writefln("%35.35s: Average %12.6f MB/s", __FUNCTION__, mbs_average / mbs_counts);
92 	if (writeCSV)
93 		csvFile.writeFile;
94 	return rc;
95 }