Commit e3f2a695 authored by Xiao Shi's avatar Xiao Shi Committed by Facebook Github Bot

move `Counts` and `Tracked` from F14MapTest.cpp to F14TestUtil.h

Summary:
Move the helper classes into F14TestUtil header so that F14SetTest could use
them as well.

Reviewed By: yfeldblum

Differential Revision: D7336571

fbshipit-source-id: 9fc96e43fe882d05b6b6fbcd075a42f5184f7d62
parent 2be7915e
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <folly/container/test/F14TestUtil.h> #include <folly/container/test/F14TestUtil.h>
using namespace folly; using namespace folly;
using namespace folly::f14;
using namespace folly::string_piece_literals; using namespace folly::string_piece_literals;
namespace { namespace {
...@@ -432,179 +433,6 @@ TEST(F14ValueMap, steady_state_stats) { ...@@ -432,179 +433,6 @@ TEST(F14ValueMap, steady_state_stats) {
LOG(INFO) << "F14ValueMap at steady state -> " << F14TableStats::compute(h); LOG(INFO) << "F14ValueMap at steady state -> " << F14TableStats::compute(h);
} }
// Tracked is implicitly constructible across tags
namespace {
struct Counts {
uint64_t copyConstruct{0};
uint64_t moveConstruct{0};
uint64_t copyConvert{0};
uint64_t moveConvert{0};
uint64_t copyAssign{0};
uint64_t moveAssign{0};
uint64_t defaultConstruct{0};
explicit Counts(
uint64_t copConstr = 0,
uint64_t movConstr = 0,
uint64_t copConv = 0,
uint64_t movConv = 0,
uint64_t copAssign = 0,
uint64_t movAssign = 0,
uint64_t def = 0)
: copyConstruct{copConstr},
moveConstruct{movConstr},
copyConvert{copConv},
moveConvert{movConv},
copyAssign{copAssign},
moveAssign{movAssign},
defaultConstruct{def} {}
uint64_t dist(Counts const& rhs) const {
auto d = [](uint64_t x, uint64_t y) { return (x - y) * (x - y); };
return d(copyConstruct, rhs.copyConstruct) +
d(moveConstruct, rhs.moveConstruct) + d(copyConvert, rhs.copyConvert) +
d(moveConvert, rhs.moveConvert) + d(copyAssign, rhs.copyAssign) +
d(moveAssign, rhs.moveAssign) +
d(defaultConstruct, rhs.defaultConstruct);
}
bool operator==(Counts const& rhs) const {
return copyConstruct == rhs.copyConstruct &&
moveConstruct == rhs.moveConstruct && copyConvert == rhs.copyConvert &&
moveConvert == rhs.moveConvert && copyAssign == rhs.copyAssign &&
moveAssign == rhs.moveAssign &&
defaultConstruct == rhs.defaultConstruct;
}
bool operator!=(Counts const& rhs) const {
return !(*this == rhs);
}
};
thread_local Counts sumCounts{};
template <int Tag>
struct Tracked {
static thread_local Counts counts;
uint64_t val_;
Tracked() : val_{0} {
sumCounts.defaultConstruct++;
counts.defaultConstruct++;
}
/* implicit */ Tracked(uint64_t val) : val_{val} {
sumCounts.copyConvert++;
counts.copyConvert++;
}
Tracked(Tracked const& rhs) : val_{rhs.val_} {
sumCounts.copyConstruct++;
counts.copyConstruct++;
}
Tracked(Tracked&& rhs) noexcept : val_{rhs.val_} {
sumCounts.moveConstruct++;
counts.moveConstruct++;
}
Tracked& operator=(Tracked const& rhs) {
val_ = rhs.val_;
sumCounts.copyAssign++;
counts.copyAssign++;
return *this;
}
Tracked& operator=(Tracked&& rhs) noexcept {
val_ = rhs.val_;
sumCounts.moveAssign++;
counts.moveAssign++;
return *this;
}
template <int T>
/* implicit */ Tracked(Tracked<T> const& rhs) : val_{rhs.val_} {
sumCounts.copyConvert++;
counts.copyConvert++;
}
template <int T>
/* implicit */ Tracked(Tracked<T>&& rhs) : val_{rhs.val_} {
sumCounts.moveConvert++;
counts.moveConvert++;
}
bool operator==(Tracked const& rhs) const {
return val_ == rhs.val_;
}
bool operator!=(Tracked const& rhs) const {
return !(*this == rhs);
}
};
template <>
thread_local Counts Tracked<0>::counts{};
template <>
thread_local Counts Tracked<1>::counts{};
template <>
thread_local Counts Tracked<2>::counts{};
template <>
thread_local Counts Tracked<3>::counts{};
template <>
thread_local Counts Tracked<4>::counts{};
template <>
thread_local Counts Tracked<5>::counts{};
void resetTracking() {
sumCounts = Counts{};
Tracked<0>::counts = Counts{};
Tracked<1>::counts = Counts{};
Tracked<2>::counts = Counts{};
Tracked<3>::counts = Counts{};
Tracked<4>::counts = Counts{};
Tracked<5>::counts = Counts{};
}
} // namespace
std::ostream& operator<<(std::ostream& xo, Counts const& counts) {
xo << "[";
std::string glue = "";
if (counts.copyConstruct > 0) {
xo << glue << counts.copyConstruct << " copy";
glue = ", ";
}
if (counts.moveConstruct > 0) {
xo << glue << counts.moveConstruct << " move";
glue = ", ";
}
if (counts.copyConvert > 0) {
xo << glue << counts.copyConvert << " copy convert";
glue = ", ";
}
if (counts.moveConvert > 0) {
xo << glue << counts.moveConvert << " move convert";
glue = ", ";
}
if (counts.copyAssign > 0) {
xo << glue << counts.copyAssign << " copy assign";
glue = ", ";
}
if (counts.moveAssign > 0) {
xo << glue << counts.moveAssign << " move assign";
glue = ", ";
}
if (counts.defaultConstruct > 0) {
xo << glue << counts.defaultConstruct << " default construct";
glue = ", ";
}
xo << "]";
return xo;
}
namespace std {
template <int Tag>
struct hash<Tracked<Tag>> {
size_t operator()(Tracked<Tag> const& tracked) const {
return tracked.val_ ^ Tag;
}
};
} // namespace std
TEST(Tracked, baseline) { TEST(Tracked, baseline) {
Tracked<0> a0; Tracked<0> a0;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <folly/container/test/F14TestUtil.h> #include <folly/container/test/F14TestUtil.h>
using namespace folly; using namespace folly;
using namespace folly::f14;
using namespace folly::string_piece_literals; using namespace folly::string_piece_literals;
namespace { namespace {
......
...@@ -108,7 +108,167 @@ struct MoveOnlyTestInt { ...@@ -108,7 +108,167 @@ struct MoveOnlyTestInt {
} }
}; };
} // namespace f14 // Tracked is implicitly constructible across tags
struct Counts {
uint64_t copyConstruct{0};
uint64_t moveConstruct{0};
uint64_t copyConvert{0};
uint64_t moveConvert{0};
uint64_t copyAssign{0};
uint64_t moveAssign{0};
uint64_t defaultConstruct{0};
explicit Counts(
uint64_t copConstr = 0,
uint64_t movConstr = 0,
uint64_t copConv = 0,
uint64_t movConv = 0,
uint64_t copAssign = 0,
uint64_t movAssign = 0,
uint64_t def = 0)
: copyConstruct{copConstr},
moveConstruct{movConstr},
copyConvert{copConv},
moveConvert{movConv},
copyAssign{copAssign},
moveAssign{movAssign},
defaultConstruct{def} {}
uint64_t dist(Counts const& rhs) const {
auto d = [](uint64_t x, uint64_t y) { return (x - y) * (x - y); };
return d(copyConstruct, rhs.copyConstruct) +
d(moveConstruct, rhs.moveConstruct) + d(copyConvert, rhs.copyConvert) +
d(moveConvert, rhs.moveConvert) + d(copyAssign, rhs.copyAssign) +
d(moveAssign, rhs.moveAssign) +
d(defaultConstruct, rhs.defaultConstruct);
}
bool operator==(Counts const& rhs) const {
return copyConstruct == rhs.copyConstruct &&
moveConstruct == rhs.moveConstruct && copyConvert == rhs.copyConvert &&
moveConvert == rhs.moveConvert && copyAssign == rhs.copyAssign &&
moveAssign == rhs.moveAssign &&
defaultConstruct == rhs.defaultConstruct;
}
bool operator!=(Counts const& rhs) const {
return !(*this == rhs);
}
};
std::ostream& operator<<(std::ostream& xo, Counts const& counts) {
xo << "[";
std::string glue = "";
if (counts.copyConstruct > 0) {
xo << glue << counts.copyConstruct << " copy";
glue = ", ";
}
if (counts.moveConstruct > 0) {
xo << glue << counts.moveConstruct << " move";
glue = ", ";
}
if (counts.copyConvert > 0) {
xo << glue << counts.copyConvert << " copy convert";
glue = ", ";
}
if (counts.moveConvert > 0) {
xo << glue << counts.moveConvert << " move convert";
glue = ", ";
}
if (counts.copyAssign > 0) {
xo << glue << counts.copyAssign << " copy assign";
glue = ", ";
}
if (counts.moveAssign > 0) {
xo << glue << counts.moveAssign << " move assign";
glue = ", ";
}
if (counts.defaultConstruct > 0) {
xo << glue << counts.defaultConstruct << " default construct";
glue = ", ";
}
xo << "]";
return xo;
}
thread_local Counts sumCounts{};
template <int Tag>
struct Tracked {
static thread_local Counts counts;
uint64_t val_;
Tracked() : val_{0} {
sumCounts.defaultConstruct++;
counts.defaultConstruct++;
}
/* implicit */ Tracked(uint64_t val) : val_{val} {
sumCounts.copyConvert++;
counts.copyConvert++;
}
Tracked(Tracked const& rhs) : val_{rhs.val_} {
sumCounts.copyConstruct++;
counts.copyConstruct++;
}
Tracked(Tracked&& rhs) noexcept : val_{rhs.val_} {
sumCounts.moveConstruct++;
counts.moveConstruct++;
}
Tracked& operator=(Tracked const& rhs) {
val_ = rhs.val_;
sumCounts.copyAssign++;
counts.copyAssign++;
return *this;
}
Tracked& operator=(Tracked&& rhs) noexcept {
val_ = rhs.val_;
sumCounts.moveAssign++;
counts.moveAssign++;
return *this;
}
template <int T>
/* implicit */ Tracked(Tracked<T> const& rhs) : val_{rhs.val_} {
sumCounts.copyConvert++;
counts.copyConvert++;
}
template <int T>
/* implicit */ Tracked(Tracked<T>&& rhs) : val_{rhs.val_} {
sumCounts.moveConvert++;
counts.moveConvert++;
}
bool operator==(Tracked const& rhs) const {
return val_ == rhs.val_;
}
bool operator!=(Tracked const& rhs) const {
return !(*this == rhs);
}
};
template <>
thread_local Counts Tracked<0>::counts{};
template <>
thread_local Counts Tracked<1>::counts{};
template <>
thread_local Counts Tracked<2>::counts{};
template <>
thread_local Counts Tracked<3>::counts{};
template <>
thread_local Counts Tracked<4>::counts{};
template <>
thread_local Counts Tracked<5>::counts{};
void resetTracking() {
sumCounts = Counts{};
Tracked<0>::counts = Counts{};
Tracked<1>::counts = Counts{};
Tracked<2>::counts = Counts{};
Tracked<3>::counts = Counts{};
Tracked<4>::counts = Counts{};
Tracked<5>::counts = Counts{};
}
std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) { std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) {
using f14::Histo; using f14::Histo;
...@@ -140,6 +300,7 @@ std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) { ...@@ -140,6 +300,7 @@ std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) {
return xo; return xo;
} }
} // namespace f14
} // namespace folly } // namespace folly
namespace std { namespace std {
...@@ -149,4 +310,11 @@ struct hash<folly::f14::MoveOnlyTestInt> { ...@@ -149,4 +310,11 @@ struct hash<folly::f14::MoveOnlyTestInt> {
return val.x; return val.x;
} }
}; };
template <int Tag>
struct hash<folly::f14::Tracked<Tag>> {
size_t operator()(folly::f14::Tracked<Tag> const& tracked) const {
return tracked.val_ ^ Tag;
}
};
} // namespace std } // namespace std
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