Skip to content

Commit

Permalink
Directly implement assignment from numeric types & nullptr to folly::…
Browse files Browse the repository at this point in the history
…dynamic

Summary: Should avoid intermediate folly::dynamic construction (and consequent cheap-but-not-free ~dynamic invocation) when possible.

Reviewed By: ot

Differential Revision: D45837998

fbshipit-source-id: 42477e3c8a0a6af138b13ad0cd7fd79aae20d4d3
  • Loading branch information
swolchok authored and facebook-github-bot committed May 18, 2023
1 parent e38a45b commit 0ce77fd
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 0 deletions.
14 changes: 14 additions & 0 deletions folly/dynamic-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,20 @@ dynamic::dynamic(Iterator first, Iterator last) : type_(ARRAY) {
new (&u_.array) Array(first, last);
}

template <
class T,
class NumericType /* = typename NumericTypeHelper<T>::type */>
dynamic& dynamic::operator=(T t) {
const auto newType = TypeInfo<NumericType>::type;
if (type_ == newType) {
*getAddress<NumericType>() = t;
} else {
destroy();
new (getAddress<NumericType>()) NumericType(t);
type_ = newType;
}
return *this;
}
//////////////////////////////////////////////////////////////////////

inline dynamic::const_iterator dynamic::begin() const {
Expand Down
11 changes: 11 additions & 0 deletions folly/dynamic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,17 @@ dynamic& dynamic::operator=(dynamic&& o) noexcept {
return *this;
}

dynamic& dynamic::operator=(std::nullptr_t) {
if (type_ == NULLT) {
// Do nothing -- nul has only one possible value.
} else {
destroy();
u_.nul = nullptr;
type_ = NULLT;
}
return *this;
}

dynamic const& dynamic::atImpl(dynamic const& idx) const& {
if (auto* parray = get_nothrow<Array>()) {
if (!idx.isInt()) {
Expand Down
9 changes: 9 additions & 0 deletions folly/dynamic.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,15 @@ struct dynamic {
dynamic& operator=(dynamic const&);
dynamic& operator=(dynamic&&) noexcept;

/*
* Minor performance optimization: allow assignment from cheap
* primitive types without creating a temporary dynamic.
*/
template <class T, class NumericType = typename NumericTypeHelper<T>::type>
dynamic& operator=(T t);

dynamic& operator=(std::nullptr_t);

/*
* For simple dynamics (not arrays or objects), this prints the
* value to an std::ostream in the expected way. Respects the
Expand Down
10 changes: 10 additions & 0 deletions folly/test/DynamicBenchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ BENCHMARK(copyBool, iters) {
}
}

BENCHMARK(assignRawBool, iters) {
bool b = true;
dynamic other = false;
folly::makeUnpredictable(b);
for (size_t i = 0; i < iters; ++i) {
other = b;
folly::doNotOptimizeAway(other);
}
}

BENCHMARK(copyShortString, iters) {
dynamic s = "short";
folly::makeUnpredictable(s);
Expand Down

0 comments on commit 0ce77fd

Please sign in to comment.