/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/IPAddress.h>
#include <fmt/core.h>
#include <glog/logging.h>
#include <folly/Benchmark.h>
#include <folly/Conv.h>
using namespace folly;
using std::string;
BENCHMARK(ipv4_to_string_inet_ntop, iters) {
folly::IPAddressV4 ipv4Addr("127.0.0.1");
in_addr ip = ipv4Addr.toAddr();
char outputString[INET_ADDRSTRLEN] = {0};
while (iters--) {
const char* val =
inet_ntop(AF_INET, &ip, outputString, sizeof(outputString));
folly::doNotOptimizeAway(val);
}
}
BENCHMARK_RELATIVE(ipv4_to_fully_qualified, iters) {
IPAddressV4 ip("127.0.0.1");
while (iters--) {
string outputString = ip.toFullyQualified();
folly::doNotOptimizeAway(outputString);
folly::doNotOptimizeAway(outputString.data());
}
}
BENCHMARK_DRAW_LINE();
BENCHMARK(ipv4_to_fully_qualified_port, iters) {
IPAddressV4 ip("255.255.255.255");
while (iters--) {
string outputString = fmt::format("{}:{}", ip.toFullyQualified(), 65535);
folly::doNotOptimizeAway(outputString);
folly::doNotOptimizeAway(outputString.data());
}
}
BENCHMARK_RELATIVE(ipv4_append_to_fully_qualified_port, iters) {
IPAddressV4 ip("255.255.255.255");
while (iters--) {
string outputString;
outputString.reserve(IPAddressV4::kMaxToFullyQualifiedSize + 1 + 5);
ip.toFullyQualifiedAppend(outputString);
outputString += ':';
folly::toAppend(65535, &outputString);
folly::doNotOptimizeAway(outputString);
folly::doNotOptimizeAway(outputString.data());
}
}
BENCHMARK_DRAW_LINE();
BENCHMARK(ipv6_to_string_inet_ntop, iters) {
IPAddressV6 ipv6Addr("F1E0:0ACE:FB94:7ADF:22E8:6DE6:9672:3725");
in6_addr ip = ipv6Addr.toAddr();
char outputString[INET6_ADDRSTRLEN] = {0};
while (iters--) {
const char* val =
inet_ntop(AF_INET6, &ip, outputString, sizeof(outputString));
folly::doNotOptimizeAway(val);
}
}
BENCHMARK_RELATIVE(ipv6_to_fully_qualified, iters) {
IPAddressV6 ip("F1E0:0ACE:FB94:7ADF:22E8:6DE6:9672:3725");
while (iters--) {
string outputString = ip.toFullyQualified();
folly::doNotOptimizeAway(outputString);
folly::doNotOptimizeAway(outputString.data());
}
}
BENCHMARK_DRAW_LINE();
BENCHMARK(ipv6_to_fully_qualified_port, iters) {
IPAddressV6 ip("F1E0:0ACE:FB94:7ADF:22E8:6DE6:9672:3725");
while (iters--) {
string outputString = fmt::format("{}:{}", ip.toFullyQualified(), 65535);
folly::doNotOptimizeAway(outputString);
folly::doNotOptimizeAway(outputString.data());
}
}
BENCHMARK_RELATIVE(ipv6_append_to_fully_qualified_port, iters) {
IPAddressV6 ip("F1E0:0ACE:FB94:7ADF:22E8:6DE6:9672:3725");
while (iters--) {
string outputString;
outputString.reserve(folly::IPAddressV6::kToFullyQualifiedSize + 1 + 5);
ip.toFullyQualifiedAppend(outputString);
outputString += ':';
folly::toAppend(65535, &outputString);
folly::doNotOptimizeAway(outputString);
folly::doNotOptimizeAway(outputString.data());
}
}
BENCHMARK_DRAW_LINE();
BENCHMARK(ipv6_ctor_valid, iters) {
while (iters--) {
try {
IPAddressV6 ip("2803:6082:18e0:2c49:1a23:9ee0:5c87:9800");
doNotOptimizeAway(ip);
} catch (const IPAddressFormatException& ex) {
doNotOptimizeAway(ex);
}
}
}
BENCHMARK_RELATIVE(ipv6_ctor_invalid, iters) {
while (iters--) {
try {
IPAddressV6 ip("2803:6082:18e0:2c49:1a23:9ee0:5c87:980r");
doNotOptimizeAway(ip);
} catch (const IPAddressFormatException& ex) {
doNotOptimizeAway(ex);
}
}
}
BENCHMARK_DRAW_LINE();
BENCHMARK(ipv6_try_from_string_valid, iters) {
while (iters--) {
auto maybeIp =
IPAddressV6::tryFromString("2803:6082:18e0:2c49:1a23:9ee0:5c87:9800");
CHECK(maybeIp.hasValue());
doNotOptimizeAway(maybeIp);
doNotOptimizeAway(maybeIp.value());
}
}
BENCHMARK_RELATIVE(ipv6_try_from_string_invalid, iters) {
while (iters--) {
auto maybeIp =
IPAddressV6::tryFromString("2803:6082:18e0:2c49:1a23:9ee0:5c87:980r");
CHECK(maybeIp.hasError());
doNotOptimizeAway(maybeIp);
doNotOptimizeAway(maybeIp.error());
}
}
// Benchmark results on Intel Xeon CPU E5-2660 @ 2.20GHz
// ============================================================================
// folly/test/IPAddressBenchmark.cpp relative time/iter iters/s
// ============================================================================
// ipv4_to_string_inet_ntop 227.13ns 4.40M
// ipv4_to_fully_qualified 1418.95% 16.01ns 62.47M
// ----------------------------------------------------------------------------
// ipv4_to_fully_qualified_port 77.51ns 12.90M
// ipv4_append_to_fully_qualified_port 133.72% 57.96ns 17.25M
// ----------------------------------------------------------------------------
// ipv6_to_string_inet_ntop 750.53ns 1.33M
// ipv6_to_fully_qualified 608.68% 123.30ns 8.11M
// ----------------------------------------------------------------------------
// ipv6_to_fully_qualified_port 150.76ns 6.63M
// ipv6_append_to_fully_qualified_port 178.73% 84.35ns 11.86M
// ----------------------------------------------------------------------------
// ipv6_ctor_valid 379.97ns 2.63M
// ipv6_ctor_invalid 10.38% 3.66us 273.22K
// ----------------------------------------------------------------------------
// ipv6_try_from_string_valid 375.34ns 2.66M
// ipv6_try_from_string_invalid 111.93% 335.34ns 2.98M
// ============================================================================
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
runBenchmarks();
return 0;
}