mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-02-09 13:46:51 +02:00
Improve hex encode performance with bytewise lookup.
Previously, hex encode looked up each nibble of the input separately. Instead use a larger lookup table containing the two-byte encoding of every possible input byte, resulting in a 1/3 reduction in encoding time. Inspired by and mostly cribbed from PostgreSQL commit e24d7708.
This commit is contained in:
parent
713f6657d3
commit
23bd392bdc
@ -50,6 +50,15 @@
|
||||
|
||||
<p>Full/incremental backup method.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-ideator id="john.naylor"/>
|
||||
<release-item-contributor id="david.steele"/>
|
||||
</release-item-contributor-list>
|
||||
|
||||
<p>Improve hex encode performance with bytewise lookup.</p>
|
||||
</release-item>
|
||||
</release-development-list>
|
||||
</release-core-list>
|
||||
</release>
|
||||
|
@ -560,6 +560,11 @@
|
||||
<contributor-id type="github">precision-software</contributor-id>
|
||||
</contributor>
|
||||
|
||||
<contributor id="john.naylor">
|
||||
<contributor-name-display>John Naylor</contributor-name-display>
|
||||
<contributor-id type="github">j-naylor</contributor-id>
|
||||
</contributor>
|
||||
|
||||
<contributor id="jordan.english">
|
||||
<contributor-name-display>Jordan English</contributor-name-display>
|
||||
<contributor-id type="github">jordanenglish</contributor-id>
|
||||
|
@ -291,10 +291,18 @@ encodeToStrSizeBase64Url(const size_t sourceSize)
|
||||
/***********************************************************************************************************************************
|
||||
Hex encoding/decoding
|
||||
***********************************************************************************************************************************/
|
||||
static const char encodeHexLookup[] = "0123456789abcdef";
|
||||
static const char encodeHexLookup[512] =
|
||||
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
"202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
|
||||
"404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
|
||||
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
|
||||
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
|
||||
"a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
|
||||
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
|
||||
"e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
|
||||
|
||||
static void
|
||||
encodeToStrHex(const unsigned char *const source, const size_t sourceSize, char *const destination)
|
||||
encodeToStrHex(const unsigned char *const source, const size_t sourceSize, char *destination)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(UCHARDATA, source);
|
||||
@ -305,17 +313,15 @@ encodeToStrHex(const unsigned char *const source, const size_t sourceSize, char
|
||||
ASSERT(source != NULL);
|
||||
ASSERT(destination != NULL);
|
||||
|
||||
unsigned int destinationIdx = 0;
|
||||
|
||||
// Encode the string from one bytes to two characters
|
||||
for (unsigned int sourceIdx = 0; sourceIdx < sourceSize; sourceIdx += 1)
|
||||
{
|
||||
destination[destinationIdx++] = encodeHexLookup[source[sourceIdx] >> 4];
|
||||
destination[destinationIdx++] = encodeHexLookup[source[sourceIdx] & 0xF];
|
||||
memcpy(destination, &encodeHexLookup[source[sourceIdx] * 2], 2);
|
||||
destination += 2;
|
||||
}
|
||||
|
||||
// Zero-terminate the string
|
||||
destination[destinationIdx] = 0;
|
||||
*destination = 0;
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ testRun(void)
|
||||
TEST_TITLE("encode");
|
||||
|
||||
const unsigned char *encode = (const unsigned char *)"string_to_encode\r\n";
|
||||
char destinationEncode[256];
|
||||
char destinationEncode[513];
|
||||
|
||||
encodeToStr(encodingHex, encode, 1, destinationEncode);
|
||||
TEST_RESULT_Z(destinationEncode, "73", "1 character encode");
|
||||
@ -189,6 +189,20 @@ testRun(void)
|
||||
encodeToStr(encodingHex, destinationDecode, decodeToBinSize(encodingHex, decodeMixed), destinationEncode), "encode");
|
||||
TEST_RESULT_Z(destinationEncode, "0123456789aabbccddeeff", "check encoded hex");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("decode/encode all values");
|
||||
|
||||
unsigned char decodedAll[256];
|
||||
|
||||
for (unsigned int decodeIdx = 0; decodeIdx < sizeof(decodedAll); decodeIdx++)
|
||||
decodedAll[decodeIdx] = (unsigned char)decodeIdx;
|
||||
|
||||
encodeToStr(encodingHex, decodedAll, sizeof(decodedAll), destinationEncode);
|
||||
TEST_RESULT_UINT(strlen(destinationEncode), 512, "all values encoded size");
|
||||
TEST_RESULT_INT(memcmp(destinationEncode, encodeHexLookup, 512), 0, "all values encoded");
|
||||
decodeToBin(encodingHex, destinationEncode, destinationDecode);
|
||||
TEST_RESULT_INT(memcmp(decodedAll, destinationDecode, sizeof(decodedAll)), 0, "all values decoded");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("decode errors");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user