Commit ace896f3 authored by Tom Jackson's avatar Tom Jackson Committed by Facebook Github Bot

Faster unhexlify

Summary:
Using already-available lookup table instead of a bunch of branching, this improves read throughput from ~750MB/s to 2.1GB/s in benchmarks.

```
before:        (time)   (rate)
BM_unhexlify   1.39ns  719.26M
after:
BM_unhexlify 470.59ps    2.13G
```

Reviewed By: philippv

Differential Revision: D4201352

fbshipit-source-id: 8393e066c45c402ccb8b537fdb25417e8e6a9511
parent be0254f3
...@@ -587,17 +587,12 @@ bool unhexlify(const InputString& input, OutputString& output) { ...@@ -587,17 +587,12 @@ bool unhexlify(const InputString& input, OutputString& output) {
} }
output.resize(input.size() / 2); output.resize(input.size() / 2);
int j = 0; int j = 0;
auto unhex = [](char c) -> int {
return c >= '0' && c <= '9' ? c - '0' :
c >= 'A' && c <= 'F' ? c - 'A' + 10 :
c >= 'a' && c <= 'f' ? c - 'a' + 10 :
-1;
};
for (size_t i = 0; i < input.size(); i += 2) { for (size_t i = 0; i < input.size(); i += 2) {
int highBits = unhex(input[i]); int highBits = detail::hexTable[static_cast<uint8_t>(input[i])];
int lowBits = unhex(input[i + 1]); int lowBits = detail::hexTable[static_cast<uint8_t>(input[i + 1])];
if (highBits < 0 || lowBits < 0) { if ((highBits | lowBits) & 0x10) {
// One of the characters wasn't a hex digit
return false; return false;
} }
output[j++] = (highBits << 4) + lowBits; output[j++] = (highBits << 4) + lowBits;
......
...@@ -17,8 +17,9 @@ ...@@ -17,8 +17,9 @@
#include <folly/String.h> #include <folly/String.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <cstdarg>
#include <folly/Benchmark.h> #include <folly/Benchmark.h>
#include <folly/Random.h>
#include <cstdarg>
#include <random> #include <random>
using namespace folly; using namespace folly;
...@@ -102,6 +103,10 @@ fbstring uriUnescapedString; ...@@ -102,6 +103,10 @@ fbstring uriUnescapedString;
const size_t kURIBmStringLength = 256; const size_t kURIBmStringLength = 256;
const uint32_t kURIPassThroughPercentage = 50; const uint32_t kURIPassThroughPercentage = 50;
fbstring hexlifyInput;
fbstring hexlifyOutput;
const size_t kHexlifyLength = 1024;
void initBenchmark() { void initBenchmark() {
std::mt19937 rnd; std::mt19937 rnd;
...@@ -145,6 +150,11 @@ void initBenchmark() { ...@@ -145,6 +150,11 @@ void initBenchmark() {
} }
uribmEscapedString = uriEscape<fbstring>(uribmString); uribmEscapedString = uriEscape<fbstring>(uribmString);
// hexlify
hexlifyInput.resize(kHexlifyLength);
Random::secureRandom(&hexlifyInput[0], kHexlifyLength);
folly::hexlify(hexlifyInput, hexlifyOutput);
} }
BENCHMARK(BM_cEscape, iters) { BENCHMARK(BM_cEscape, iters) {
...@@ -175,6 +185,18 @@ BENCHMARK(BM_uriUnescape, iters) { ...@@ -175,6 +185,18 @@ BENCHMARK(BM_uriUnescape, iters) {
} }
} }
BENCHMARK(BM_unhexlify, iters) {
// iters/sec = bytes output per sec
std::string unhexed;
folly::StringPiece hex = hexlifyOutput;
for (; iters >= hex.size(); iters -= hex.size()) {
folly::unhexlify(hex, unhexed);
}
iters -= iters % 2; // round down to an even number of chars
hex = hex.subpiece(0, iters);
folly::unhexlify(hex, unhexed);
}
} // namespace } // namespace
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment