From 46e3ed2921bd4e5de81fbc36fcb6a82d30d1499f Mon Sep 17 00:00:00 2001 From: Marcin Pawlowski Date: Tue, 19 Aug 2014 22:25:05 -0700 Subject: [PATCH] made toAppendDelim better Summary: preallocate once and for all, so that we are really malloc efficient in toAppendDelim Test Plan: unit tests Reviewed By: marcelo.juchem@fb.com FB internal diff: D1496310 Tasks: 4886092 --- folly/Conv.h | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/folly/Conv.h b/folly/Conv.h index 83b36be8..c624b199 100644 --- a/folly/Conv.h +++ b/folly/Conv.h @@ -655,7 +655,14 @@ size_t estimateSpaceToReserve(size_t sofar, const T& v) { template void reserveInTarget(const Ts&...vs) { - getLastElement(vs...)->reserve(detail::estimateSpaceToReserve(0, vs...)); + getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...)); +} + +template +void reserveInTargetDelim(const Delimiter& d, const Ts&...vs) { + static_assert(sizeof...(vs) >= 2, "Needs at least 2 args"); + size_t fordelim = (sizeof...(vs) - 2) * estimateSpaceToReserve(0, d); + getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...)); } /** @@ -679,6 +686,29 @@ toAppendStrImpl(const T& v, const Ts&... vs) { toAppend(v, getLastElement(vs...)); toAppendStrImpl(vs...); } + +template +typename std::enable_if< + IsSomeString::type> + ::value>::type +toAppendDelimStrImpl(const Delimiter& delim, const T& v, Tgt result) { + toAppend(v, result); +} + +template +typename std::enable_if= 2 + && IsSomeString< + typename std::remove_pointer< + typename detail::last_element::type + >::type>::value>::type +toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) { + // we are really careful here, calling toAppend with just one element does + // not try to estimate space needed (as we already did that). If we call + // toAppend(v, delim, ....) we would do unnecesary size calculation + toAppend(v, detail::getLastElement(vs...)); + toAppend(delim, detail::getLastElement(vs...)); + toAppendDelimStrImpl(delim, vs...); +} } // folly::detail @@ -726,15 +756,15 @@ toAppendDelim(const Delimiter& delim, const T& v, Tgt* tgt) { /** * Append to string with a delimiter in between elements. */ -template -typename std::enable_if= 2 +template +typename std::enable_if= 3 && IsSomeString< typename std::remove_pointer< typename detail::last_element::type >::type>::value>::type -toAppendDelim(const Delimiter& delim, const T& v, const Ts&... vs) { - toAppend(v, delim, detail::getLastElement(vs...)); - toAppendDelim(delim, vs...); +toAppendDelim(const Delimiter& delim, const Ts&... vs) { + detail::reserveInTargetDelim(delim, vs...); + detail::toAppendDelimStrImpl(delim, vs...); } /** -- 2.34.1