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
}
output.resize(input.size() / 2);
int j = 0;
}
output.resize(input.size() / 2);
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 lowBits = unhex(input[i + 1]);
- if (highBits < 0 || lowBits < 0) {
+ int highBits = detail::hexTable[static_cast<uint8_t>(input[i])];
+ int lowBits = detail::hexTable[static_cast<uint8_t>(input[i + 1])];
+ if ((highBits | lowBits) & 0x10) {
+ // One of the characters wasn't a hex digit
return false;
}
output[j++] = (highBits << 4) + lowBits;
return false;
}
output[j++] = (highBits << 4) + lowBits;
#include <folly/String.h>
#include <boost/algorithm/string.hpp>
#include <folly/String.h>
#include <boost/algorithm/string.hpp>
#include <folly/Benchmark.h>
#include <folly/Benchmark.h>
+#include <folly/Random.h>
+#include <cstdarg>
#include <random>
using namespace folly;
#include <random>
using namespace folly;
const size_t kURIBmStringLength = 256;
const uint32_t kURIPassThroughPercentage = 50;
const size_t kURIBmStringLength = 256;
const uint32_t kURIPassThroughPercentage = 50;
+fbstring hexlifyInput;
+fbstring hexlifyOutput;
+const size_t kHexlifyLength = 1024;
+
void initBenchmark() {
std::mt19937 rnd;
void initBenchmark() {
std::mt19937 rnd;
}
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) {
+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
//////////////////////////////////////////////////////////////////////