Sync changes from upstream repository

Co-authored-by: Andrew le Bihan <andy@mcneel.com>
Co-authored-by: Brian Gillespie <brian@mcneel.com>
Co-authored-by: Dale Lear <dalelear@mcneel.com>
Co-authored-by: Giulio Piacentino <giulio@mcneel.com>
Co-authored-by: Greg Arden <greg@mcneel.com>
Co-authored-by: Lars <lars@mcneel.com>
Co-authored-by: Lowell <lowell@mcneelcom>
Co-authored-by: Nathan Letwory <nathan@mcneel.com>
Co-authored-by: Pierre Cuvilliers <pierre@mcneel.com>
Co-authored-by: Tim Hemmelman <tim@mcneel.com>
This commit is contained in:
Bozo The Builder
2020-12-16 05:49:44 -08:00
parent 990401a8f5
commit 488533eb7a
54 changed files with 4026 additions and 898 deletions

View File

@@ -75,35 +75,42 @@ ON__UINT16 ON_CRC16( ON__UINT16 current_remainder, size_t count, const void* p )
{
ON__UINT16 r1;
// update crc remainder
while (count >= 8)
{
// while() loop unrolled for speed
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
current_remainder = (current_remainder << 8) ^ (*b++);
current_remainder ^= r1;
count -= 8;
}
// Dale Lear September 2020
// I was comparing 16-bit crc, 32-bit crc, MAD5 and SHA-1 hash calcualation speeds.
// It turns out, that compilers and optimizers have improved a fair bit since 1994 when this code was written.
// Manual loop unrolling doesn't help (this used to make a measurable difference in 1994 when we used Watcom C on Win 3.1.)
// The TestHashSpeed command tests hashing speeds. Short story - use either ON_CRC32 or ON_SHA1.
//while (count >= 8)
// {
// // while() loop unrolled for speed
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
// current_remainder = (current_remainder << 8) ^ (*b++);
// current_remainder ^= r1;
// count -= 8;
//}
while (count--)
{
r1 = ON_CRC16_CCITT_TABLE[(current_remainder & ((ON__UINT16)0xff00))>>8];
@@ -267,4 +274,195 @@ ON__UINT32 ON_CRC32( ON__UINT32 current_remainder, size_t count, const void* p )
}
/*
Description:
Test speeds of various hash algoritmhs.
Parameters:
byte_count - [in]
Number of bytes to hash. This number is rounded up to the nearest multiple of 1024.
crc16 - [in/out]
If crc16 is not nullptr, then 16 bit CRC hashing is tested using function ON_CRC16().
crc32 - [in/out]
If crc32 is not nullptr, then 32 bit CRC hashing is tested using function ON_CRC32().
md5_hash - [in/out]
If md5_hash is not nullptr, then MD5 hashing is tested using class ON_MD5.
sha1_hash - [in/out]
If sha1_hash is not nullptr, then SHA-1 hashing is tested class ON_SHA1.
elapsed_time_in_seconds - [out]
elapsed_time_in_seconds[0] = 16 bit CRC hash time in seconds.
elapsed_time_in_seconds[1] = 32 bit CRC hash time in seconds.
elapsed_time_in_seconds[2] = MD5 hash time in seconds.
elapsed_time_in_seconds[3] = SHA-1 hash time in seconds.
If a hash was tested, then number of seconds it took to compute the hash is returned.
Otherwise ON_DBL_QNAN is returned.
*/
void ON_TestHashSpeed(
size_t byte_count,
ON__UINT16* crc16,
ON__UINT32* crc32,
ON_MD5_Hash* md5_hash,
ON_SHA1_Hash* sha1_hash,
double elapsed_time_in_seconds[4]
)
{
for (int i = 0; i < 4; ++i)
elapsed_time_in_seconds[i] = ON_DBL_QNAN;
ON_RandomNumberGenerator rng;
ON_SimpleArray<ON__UINT32> buffer_array(1024);
for (int i = 0; i < buffer_array.Capacity(); ++i)
buffer_array.Append(rng.RandomNumber());
const ON__UINT32* buffer = buffer_array.Array();
const size_t sizeof_buffer = buffer_array.UnsignedCount() * sizeof(buffer[0]);
ON_StopWatch sw;
if (nullptr != crc16)
{
sw.Start();
ON__UINT16 h16 = 0;
for (size_t count = 0; count < byte_count; count += sizeof_buffer)
h16 = ON_CRC16(h16, sizeof_buffer, buffer);
*crc16 = h16;
sw.Stop();
elapsed_time_in_seconds[0] = sw.ElapsedTime();
}
if (nullptr != crc32)
{
sw.Start();
ON__UINT32 h32 = 0;
for (size_t count = 0; count < byte_count; count += sizeof_buffer)
h32 = ON_CRC32(h32, sizeof_buffer, buffer);
*crc32 = h32;
sw.Stop();
elapsed_time_in_seconds[1] = sw.ElapsedTime();
}
if (nullptr != md5_hash)
{
sw.Start();
ON_MD5 md5;
for (size_t count = 0; count < byte_count; count += sizeof_buffer)
md5.AccumulateBytes(buffer, sizeof_buffer);
*md5_hash = md5.Hash();
sw.Stop();
elapsed_time_in_seconds[2] = sw.ElapsedTime();
}
if (nullptr != sha1_hash)
{
sw.Start();
ON_SHA1 sha1;
for (size_t count = 0; count < byte_count; count += sizeof_buffer)
sha1.AccumulateBytes(buffer, sizeof_buffer);
*sha1_hash = sha1.Hash();
sw.Stop();
elapsed_time_in_seconds[3] = sw.ElapsedTime();
}
return;
}
void ON_TestHashSpeed(
size_t byte_count,
bool bTestCRC16,
bool bTestCRC32,
bool bTestMD5,
bool bTestSHA1,
ON_TextLog& text_log
)
{
ON__UINT16 crc16 = 0;
ON__UINT32 crc32 = 0;
ON_MD5_Hash md5_hash = ON_MD5_Hash::ZeroDigest;
ON_SHA1_Hash sha1_hash = ON_SHA1_Hash::ZeroDigest;
double elapsed_time_in_seconds[4] = {};
byte_count = (byte_count / 1024) * 1024;
ON_TestHashSpeed(
byte_count,
bTestCRC16 ? &crc16 : nullptr,
bTestCRC32 ? &crc32 : nullptr,
bTestMD5 ? &md5_hash : nullptr,
bTestSHA1 ? &sha1_hash : nullptr,
elapsed_time_in_seconds
);
#if defined(ON_DEBUG)
const char* str = "Debug opennurbs hashing times for ";
#else
const char* str = "Release opennurbs hashing times for ";
#endif
text_log.Print(str);
const size_t one_kb = 1024;
const size_t one_mb = one_kb * one_kb;
const size_t one_gb = one_kb * one_kb * one_kb;
if (byte_count >= one_gb && 0 == byte_count % one_gb)
text_log.Print("%zu GB:\n", byte_count / one_gb);
else if (byte_count >= one_mb && 0 == byte_count % one_mb)
text_log.Print("%zu MB:\n", byte_count / one_mb);
else if (byte_count >= one_kb && 0 == byte_count % one_kb)
text_log.Print("%zu KB:\n", byte_count / one_kb);
else
text_log.Print("%zu bytes:\n", byte_count);
const ON_TextLogIndent indent1(text_log);
const ON_String hashname[4] = {
"16 bit CRC",
"32 bit crc",
"MD5",
"SHA-1"
};
const bool bTested[4] = { bTestCRC16 ,bTestCRC32 ,bTestMD5 ,bTestSHA1 };
// Set i0 = index of the fastest hash test
int i0 = -1;
for (int i = 0; i < 4; i++)
{
if (bTested[i] && elapsed_time_in_seconds[i] > 0.0)
{
if (i0 < 0 || elapsed_time_in_seconds[i] < elapsed_time_in_seconds[i0])
i0 = i;
}
}
for (int i = 0; i < 4; ++i)
{
if (bTested[i])
{
const int test_dex = 0;
text_log.Print("%s: %g seconds.", static_cast<const char*>(hashname[i]), elapsed_time_in_seconds[i]);
if (elapsed_time_in_seconds[i] > 0.0 && i0 >= 0 && i0 != i)
text_log.Print(" (%g x %s)", elapsed_time_in_seconds[i] / elapsed_time_in_seconds[i0], static_cast<const char*>(hashname[i0]));
text_log.PrintNewLine();
}
}
}
void ON_TestHashSpeed(
size_t byte_count,
ON_TextLog& text_log
)
{
const bool bTestCRC16 = true;
const bool bTestCRC32 = true;
const bool bTestMD5 = true;
const bool bTestSHA1 = true;
ON_TestHashSpeed(
byte_count,
bTestCRC16,
bTestCRC32,
bTestMD5,
bTestSHA1,
text_log
);
}