mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-24 12:34:53 +08:00
simplify the benchmark
This commit is contained in:
parent
62fb615be9
commit
62ed60e95f
@ -3,7 +3,7 @@ include(FetchContent)
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
counters
|
counters
|
||||||
GIT_REPOSITORY https://github.com/lemire/counters.git
|
GIT_REPOSITORY https://github.com/lemire/counters.git
|
||||||
GIT_TAG v2.0.0
|
GIT_TAG v2.1.0
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(counters)
|
FetchContent_MakeAvailable(counters)
|
||||||
|
|||||||
@ -26,6 +26,28 @@ void pretty_print(size_t volume, size_t bytes, std::string name,
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *seek_ip_end(const char *p, const char *pend) {
|
||||||
|
const char *current = p;
|
||||||
|
size_t count = 0;
|
||||||
|
for (; current != pend; ++current) {
|
||||||
|
if (*current == '.') {
|
||||||
|
count++;
|
||||||
|
if (count == 3) {
|
||||||
|
++current;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (current != pend) {
|
||||||
|
if (*current <= '9' && *current >= '0') {
|
||||||
|
++current;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
int parse_u8_fastfloat(const char *&p, const char *pend, uint8_t *out) {
|
int parse_u8_fastfloat(const char *&p, const char *pend, uint8_t *out) {
|
||||||
if (p == pend)
|
if (p == pend)
|
||||||
return 0;
|
return 0;
|
||||||
@ -39,8 +61,9 @@ int parse_u8_fastfloat(const char *&p, const char *pend, uint8_t *out) {
|
|||||||
|
|
||||||
static inline int parse_u8_fromchars(const char *&p, const char *pend,
|
static inline int parse_u8_fromchars(const char *&p, const char *pend,
|
||||||
uint8_t *out) {
|
uint8_t *out) {
|
||||||
if (p == pend)
|
if (p == pend) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
auto r = std::from_chars(p, pend, *out);
|
auto r = std::from_chars(p, pend, *out);
|
||||||
if (r.ec == std::errc()) {
|
if (r.ec == std::errc()) {
|
||||||
p = r.ptr;
|
p = r.ptr;
|
||||||
@ -50,26 +73,35 @@ static inline int parse_u8_fromchars(const char *&p, const char *pend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Parser>
|
template <typename Parser>
|
||||||
static inline int parse_ip_line(const char *&p, const char *pend, uint32_t &sum,
|
std::pair<bool, uint32_t> simple_parse_ip_line(const char *p, const char *pend,
|
||||||
Parser parse_uint8) {
|
Parser parse_uint8) {
|
||||||
uint8_t o = 0;
|
uint8_t v1;
|
||||||
for (int i = 0; i < 4; ++i) {
|
if (!parse_uint8(p, pend, &v1)) {
|
||||||
if (!parse_uint8(p, pend, &o))
|
return {false, 0};
|
||||||
return 0;
|
|
||||||
sum += o;
|
|
||||||
if (i != 3) {
|
|
||||||
if (p == pend || *p != '.')
|
|
||||||
return 0;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// consume optional '\r'
|
if (p == pend || *p++ != '.') {
|
||||||
if (p != pend && *p == '\r')
|
return {false, 0};
|
||||||
++p;
|
}
|
||||||
// expect '\n' or end
|
uint8_t v2;
|
||||||
if (p != pend && *p == '\n')
|
if (!parse_uint8(p, pend, &v2)) {
|
||||||
++p;
|
return {false, 0};
|
||||||
return 1;
|
}
|
||||||
|
if (p == pend || *p++ != '.') {
|
||||||
|
return {false, 0};
|
||||||
|
}
|
||||||
|
uint8_t v3;
|
||||||
|
if (!parse_uint8(p, pend, &v3)) {
|
||||||
|
return {false, 0};
|
||||||
|
}
|
||||||
|
if (p == pend || *p++ != '.') {
|
||||||
|
return {false, 0};
|
||||||
|
}
|
||||||
|
uint8_t v4;
|
||||||
|
if (!parse_uint8(p, pend, &v4)) {
|
||||||
|
return {false, 0};
|
||||||
|
}
|
||||||
|
return {true, (uint32_t(v1) << 24) | (uint32_t(v2) << 16) |
|
||||||
|
(uint32_t(v3) << 8) | uint32_t(v4)};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string make_ip_line(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
static std::string make_ip_line(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||||
@ -87,19 +119,22 @@ static std::string make_ip_line(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
constexpr size_t N = 500000;
|
constexpr size_t N = 15000;
|
||||||
std::mt19937 rng(1234);
|
std::mt19937 rng(1234);
|
||||||
std::uniform_int_distribution<int> dist(0, 255);
|
std::uniform_int_distribution<int> dist(0, 255);
|
||||||
|
|
||||||
std::string buf;
|
std::string buf;
|
||||||
buf.reserve(N * 16);
|
constexpr size_t ip_size = 16;
|
||||||
|
buf.reserve(N * ip_size);
|
||||||
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
uint8_t a = (uint8_t)dist(rng);
|
uint8_t a = (uint8_t)dist(rng);
|
||||||
uint8_t b = (uint8_t)dist(rng);
|
uint8_t b = (uint8_t)dist(rng);
|
||||||
uint8_t c = (uint8_t)dist(rng);
|
uint8_t c = (uint8_t)dist(rng);
|
||||||
uint8_t d = (uint8_t)dist(rng);
|
uint8_t d = (uint8_t)dist(rng);
|
||||||
buf += make_ip_line(a, b, c, d);
|
std::string ip_line = make_ip_line(a, b, c, d);
|
||||||
|
ip_line.resize(ip_size, ' '); // pad to fixed size
|
||||||
|
buf.append(ip_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sentinel to allow 4-byte loads at end
|
// sentinel to allow 4-byte loads at end
|
||||||
@ -108,30 +143,21 @@ int main() {
|
|||||||
const size_t bytes = buf.size() - 4; // exclude sentinel from throughput
|
const size_t bytes = buf.size() - 4; // exclude sentinel from throughput
|
||||||
const size_t volume = N;
|
const size_t volume = N;
|
||||||
|
|
||||||
// validate correctness
|
volatile uint32_t sink = 0;
|
||||||
{
|
|
||||||
const char *start = buf.data();
|
|
||||||
const char *end = buf.data() + bytes;
|
|
||||||
const char *p = start;
|
|
||||||
const char *pend = end;
|
|
||||||
uint32_t sum = 0;
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
|
||||||
int ok = parse_ip_line(p, pend, sum, parse_u8_fromchars);
|
|
||||||
if (!ok) {
|
|
||||||
std::fprintf(stderr, "fromchars parse failed at line %zu\n", i);
|
|
||||||
std::abort();
|
|
||||||
}
|
|
||||||
p = start;
|
|
||||||
pend = end;
|
|
||||||
ok = parse_ip_line(p, pend, sum, parse_u8_fastfloat);
|
|
||||||
if (!ok) {
|
|
||||||
std::fprintf(stderr, "fastswar parse failed at line %zu\n", i);
|
|
||||||
std::abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t sink = 0;
|
pretty_print(volume, bytes, "just_seek_ip_end (no parse)",
|
||||||
|
counters::bench([&]() {
|
||||||
|
const char *p = buf.data();
|
||||||
|
const char *pend = buf.data() + bytes;
|
||||||
|
uint32_t sum = 0;
|
||||||
|
int ok = 0;
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
const char *q = seek_ip_end(p, pend);
|
||||||
|
sum += (uint32_t)(q - p);
|
||||||
|
p += ip_size;
|
||||||
|
}
|
||||||
|
sink += sum;
|
||||||
|
}));
|
||||||
|
|
||||||
pretty_print(volume, bytes, "parse_ip_std_fromchars", counters::bench([&]() {
|
pretty_print(volume, bytes, "parse_ip_std_fromchars", counters::bench([&]() {
|
||||||
const char *p = buf.data();
|
const char *p = buf.data();
|
||||||
@ -139,9 +165,13 @@ int main() {
|
|||||||
uint32_t sum = 0;
|
uint32_t sum = 0;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
ok = parse_ip_line(p, pend, sum, parse_u8_fromchars);
|
auto [ok, ip] =
|
||||||
if (!ok)
|
simple_parse_ip_line(p, pend, parse_u8_fromchars);
|
||||||
|
sum += ip;
|
||||||
|
if (!ok) {
|
||||||
std::abort();
|
std::abort();
|
||||||
|
}
|
||||||
|
p += ip_size;
|
||||||
}
|
}
|
||||||
sink += sum;
|
sink += sum;
|
||||||
}));
|
}));
|
||||||
@ -152,13 +182,16 @@ int main() {
|
|||||||
uint32_t sum = 0;
|
uint32_t sum = 0;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
ok = parse_ip_line(p, pend, sum, parse_u8_fastfloat);
|
auto [ok, ip] =
|
||||||
if (!ok)
|
simple_parse_ip_line(p, pend, parse_u8_fastfloat);
|
||||||
|
sum += ip;
|
||||||
|
if (!ok) {
|
||||||
std::abort();
|
std::abort();
|
||||||
|
}
|
||||||
|
p += ip_size;
|
||||||
}
|
}
|
||||||
sink += sum;
|
sink += sum;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
std::printf("sink=%u\n", sink);
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user