Commit 587427e7 authored by Zejun Wu's avatar Zejun Wu Committed by Anton Likhtarov

Specialize string to identical string conversion

Summary:
Avoid copying underlying char array in to<string>(const string&) and
to<fbstring>(const fbstring&).

Test Plan: fbconfig -r $redteamisthebestteam/$nekomikoreimu && fbmake

Reviewed By: ldbrandy@fb.com

Subscribers: jonp, folly@lists

FB internal diff: D1368183

Tasks: 4263125
parent aed6ef6f
......@@ -526,24 +526,56 @@ toAppendDelim(const Delimiter& delim, const T& v, const Ts&... vs) {
toAppendDelim(delim, vs...);
}
/**
* to<SomeString>(SomeString str) returns itself. As both std::string and
* folly::fbstring use Copy-on-Write, it's much more efficient by
* avoiding copying the underlying char array.
*/
template <class Tgt, class Src>
typename std::enable_if<
IsSomeString<Tgt>::value && std::is_same<Tgt, Src>::value,
Tgt>::type
to(const Src & value) {
return value;
}
/**
* to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
* for all types.
*/
template <class Tgt, class... Ts>
typename std::enable_if<IsSomeString<Tgt>::value, Tgt>::type
typename std::enable_if<
IsSomeString<Tgt>::value && (
sizeof...(Ts) != 1 ||
!std::is_same<Tgt, typename detail::last_element<Ts...>::type>::value),
Tgt>::type
to(const Ts&... vs) {
Tgt result;
toAppend(vs..., &result);
return result;
}
/**
* toDelim<SomeString>(SomeString str) returns itself.
*/
template <class Tgt, class Delim, class Src>
typename std::enable_if<
IsSomeString<Tgt>::value && std::is_same<Tgt, Src>::value,
Tgt>::type
toDelim(const Delim& delim, const Src & value) {
return value;
}
/**
* toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
* back-end for all types.
*/
template <class Tgt, class Delim, class... Ts>
typename std::enable_if<IsSomeString<Tgt>::value, Tgt>::type
typename std::enable_if<
IsSomeString<Tgt>::value && (
sizeof...(Ts) != 1 ||
!std::is_same<Tgt, typename detail::last_element<Ts...>::type>::value),
Tgt>::type
toDelim(const Delim& delim, const Ts&... vs) {
Tgt result;
toAppendDelim(delim, vs..., &result);
......
......@@ -389,6 +389,14 @@ TEST(Conv, BadStringToIntegral) {
}
}
template <class String>
void testIdenticalTo() {
String s("Yukkuri shiteitte ne!!!");
String result = to<String>(s);
EXPECT_EQ(result, s);
}
template <class String>
void testVariadicTo() {
String s;
......@@ -403,6 +411,17 @@ void testVariadicTo() {
EXPECT_EQ(s, "Lorem ipsum 1234 dolor amet 567.89.");
}
template <class String>
void testIdenticalToDelim() {
String s("Yukkuri shiteitte ne!!!");
String charDelim = toDelim<String>('$', s);
EXPECT_EQ(charDelim, s);
String strDelim = toDelim<String>(String(">_<"), s);
EXPECT_EQ(strDelim, s);
}
template <class String>
void testVariadicToDelim() {
String s;
......@@ -427,11 +446,15 @@ TEST(Conv, NullString) {
}
TEST(Conv, VariadicTo) {
testIdenticalTo<string>();
testIdenticalTo<fbstring>();
testVariadicTo<string>();
testVariadicTo<fbstring>();
}
TEST(Conv, VariadicToDelim) {
testIdenticalToDelim<string>();
testIdenticalToDelim<fbstring>();
testVariadicToDelim<string>();
testVariadicToDelim<fbstring>();
}
......@@ -911,6 +934,35 @@ void u2aAppendFollyBM(unsigned int n, uint64_t value) {
}
}
template <class String>
struct StringIdenticalToBM {
void operator()(unsigned int n, size_t len) const {
String s;
BENCHMARK_SUSPEND { s.append(len, '0'); }
FOR_EACH_RANGE (i, 0, n) {
String result = to<String>(s);
doNotOptimizeAway(result.size());
}
}
};
template <class String>
struct StringVariadicToBM {
void operator()(unsigned int n, size_t len) const {
String s;
BENCHMARK_SUSPEND { s.append(len, '0'); }
FOR_EACH_RANGE (i, 0, n) {
String result = to<String>(s, nullptr);
doNotOptimizeAway(result.size());
}
}
};
static const StringIdenticalToBM<std::string> stringIdenticalToBM;
static const StringVariadicToBM<std::string> stringVariadicToBM;
static const StringIdenticalToBM<fbstring> fbstringIdenticalToBM;
static const StringVariadicToBM<fbstring> fbstringVariadicToBM;
#define DEFINE_BENCHMARK_GROUP(n) \
BENCHMARK_PARAM(u64ToAsciiClassicBM, n); \
BENCHMARK_RELATIVE_PARAM(u64ToAsciiTableBM, n); \
......@@ -969,6 +1021,20 @@ DEFINE_BENCHMARK_GROUP(19);
#undef DEFINE_BENCHMARK_GROUP
#define DEFINE_BENCHMARK_GROUP(T, n) \
BENCHMARK_PARAM(T ## VariadicToBM, n); \
BENCHMARK_RELATIVE_PARAM(T ## IdenticalToBM, n); \
BENCHMARK_DRAW_LINE();
DEFINE_BENCHMARK_GROUP(string, 32);
DEFINE_BENCHMARK_GROUP(string, 1024);
DEFINE_BENCHMARK_GROUP(string, 32768);
DEFINE_BENCHMARK_GROUP(fbstring, 32);
DEFINE_BENCHMARK_GROUP(fbstring, 1024);
DEFINE_BENCHMARK_GROUP(fbstring, 32768);
#undef DEFINE_BENCHMARK_GROUP
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);
......
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