: asV6().toFullyQualified();
}
+ /// Same as toFullyQualified but append to an output string.
+ void toFullyQualifiedAppend(std::string& out) const {
+ return isV4() ? asV4().toFullyQualifiedAppend(out)
+ : asV6().toFullyQualifiedAppend(out);
+ }
+
// Address version (4 or 6)
uint8_t version() const {
return isV4() ? asV4().version()
return detail::fastIpv4ToString(addr_.inAddr_);
}
+// public
+void IPAddressV4::toFullyQualifiedAppend(std::string& out) const {
+ detail::fastIpv4AppendToString(addr_.inAddr_, out);
+}
+
// public
string IPAddressV4::toInverseArpaName() const {
return sformat(
*/
class IPAddressV4 {
public:
+ // Max size of std::string returned by toFullyQualified.
+ static constexpr size_t kMaxToFullyQualifiedSize =
+ 4 /*words*/ * 3 /*max chars per word*/ + 3 /*separators*/;
+
// returns true iff the input string can be parsed as an ipv4-address
static bool validate(StringPiece ip);
// @see IPAddress#toFullyQualified
std::string toFullyQualified() const { return str(); }
+ // @see IPAddress#toFullyQualifiedAppend
+ void toFullyQualifiedAppend(std::string& out) const;
+
// @see IPAddress#version
uint8_t version() const { return 4; }
return detail::fastIpv6ToString(addr_.in6Addr_);
}
+// public
+void IPAddressV6::toFullyQualifiedAppend(std::string& out) const {
+ detail::fastIpv6AppendToString(addr_.in6Addr_, out);
+}
+
// public
string IPAddressV6::toInverseArpaName() const {
constexpr folly::StringPiece lut = "0123456789abcdef";
// @see IPAddress#toFullyQualified
std::string toFullyQualified() const;
+ // @see IPAddress#toFullyQualifiedAppend
+ void toFullyQualifiedAppend(std::string& out) const;
+
std::string toInverseArpaName() const;
// @see IPAddress#str
*buffer = buf;
}
-inline std::string fastIpv4ToString(const in_addr& inAddr) {
+inline size_t fastIpV4ToBufferUnsafe(const in_addr& inAddr, char* str) {
const uint8_t* octets = reinterpret_cast<const uint8_t*>(&inAddr.s_addr);
- char str[sizeof("255.255.255.255")];
char* buf = str;
writeIntegerString<uint8_t, 3>(octets[0], &buf);
*(buf++) = '.';
writeIntegerString<uint8_t, 3>(octets[3], &buf);
- return std::string(str, size_t(buf - str));
+ return buf - str;
}
-inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
+inline std::string fastIpv4ToString(const in_addr& inAddr) {
+ char str[sizeof("255.255.255.255")];
+ return std::string(str, fastIpV4ToBufferUnsafe(inAddr, str));
+}
+
+inline void fastIpv4AppendToString(const in_addr& inAddr, std::string& out) {
+ char str[sizeof("255.255.255.255")];
+ out.append(str, fastIpV4ToBufferUnsafe(inAddr, str));
+}
+
+inline size_t fastIpv6ToBufferUnsafe(const in6_addr& in6Addr, char* str) {
#ifdef _MSC_VER
const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.u.Word);
#else
const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.s6_addr16);
#endif
- char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
char* buf = str;
for (int i = 0; i < 8; ++i) {
}
}
- return std::string(str, size_t(buf - str));
+ return buf - str;
+}
+
+inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
+ char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
+ return std::string(str, fastIpv6ToBufferUnsafe(in6Addr, str));
+}
+
+inline void fastIpv6AppendToString(const in6_addr& in6Addr, std::string& out) {
+ char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
+ out.append(str, fastIpv6ToBufferUnsafe(in6Addr, str));
}
}
}
* limitations under the License.
*/
+#include <folly/Conv.h>
#include <folly/IPAddress.h>
#include <glog/logging.h>
BENCHMARK_DRAW_LINE()
+BENCHMARK(ipv4_to_fully_qualified_port, iters) {
+ IPAddressV4 ip("255.255.255.255");
+ while (iters--) {
+ string outputString = to<std::string>(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();
}
}
+BENCHMARK_DRAW_LINE()
+
+BENCHMARK(ipv6_to_fully_qualified_port, iters) {
+ IPAddressV6 ip("F1E0:0ACE:FB94:7ADF:22E8:6DE6:9672:3725");
+ while (iters--) {
+ string outputString = to<std::string>(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 results on Intel Xeon CPU E5-2660 @ 2.20GHz
// ============================================================================
// folly/test/IPAddressBenchmark.cpp relative time/iter iters/s
// ============================================================================
-// ipv4_to_string_inet_ntop 237.87ns 4.20M
-// ipv4_to_fully_qualified 362.31% 65.65ns 15.23M
+// 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_string_inet_ntop 768.60ns 1.30M
-// ipv6_to_fully_qualified 821.81% 93.53ns 10.69M
+// ipv6_to_fully_qualified_port 150.76ns 6.63M
+// ipv6_append_to_fully_qualified_port 178.73% 84.35ns 11.86M
// ============================================================================
int main(int argc, char *argv[]) {
EXPECT_EQ("0000:0000:0000:0000:0000:0000:0000:0001", ip.toFullyQualified())
<< ip;
}
-TEST(IPAddress, ToFullyQualifiedSize) {
+TEST(IPAddress, ToFullyQualifiedAppendV6) {
+ IPAddress ip("2620:0:1cfe:face:b00c::3");
+ std::string result;
+ ip.toFullyQualifiedAppend(result);
+ EXPECT_EQ("2620:0000:1cfe:face:b00c:0000:0000:0003", result) << ip;
+}
+TEST(IPAddress, ToFullyQualifiedAppendV4) {
+ IPAddress ip("127.0.0.1");
+ std::string result;
+ ip.toFullyQualifiedAppend(result);
+ EXPECT_EQ("127.0.0.1", result) << ip;
+}
+TEST(IPAddress, ToFullyQualifiedSizeV6) {
auto actual = IPAddressV6::kToFullyQualifiedSize;
auto expected = IPAddress("::").toFullyQualified().size();
EXPECT_EQ(expected, actual);
}
+TEST(IPAddress, MaxToFullyQualifiedSizeV4) {
+ auto actual = IPAddressV4::kMaxToFullyQualifiedSize;
+ auto expected = IPAddress("255.255.255.255").toFullyQualified().size();
+ EXPECT_EQ(expected, actual);
+}
// test v4-v6 mapped addresses
TEST_P(IPAddressMappedTest, MappedEqual) {