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

add `getAllocatedMemorySize` for F14 maps on all platforms

Summary:
D7544180 introduced the `getAllocatedMemorySize` method. This diff adds it for
platforms where SSE2 instructions are not available.

Reviewed By: nbronson

Differential Revision: D7715573

fbshipit-source-id: af35f2dedf4a479895163d9dc18795ba397860f7
parent c4c78a73
......@@ -40,22 +40,53 @@
#if !FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
#include <string>
#include <unordered_map>
namespace folly {
namespace f14 {
namespace detail {
template <typename K>
struct CachedHashOverhead : std::integral_constant<std::size_t, 0> {};
template <typename... Args>
struct CachedHashOverhead<std::basic_string<Args...>>
: std::integral_constant<std::size_t, sizeof(std::size_t)> {};
template <typename K, typename M, typename H, typename E, typename A>
class F14ValueMap : public std::unordered_map<K, M, H, E, A> {
class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
using Super = std::unordered_map<K, M, H, E, A>;
public:
using Super::Super;
F14BasicMap() : Super() {}
// Accounts for allocated memory only, does not include sizeof(*this).
typename Super::size_type getAllocatedMemorySize() const {
auto nodeSize = sizeof(typename Super::pointer) +
CachedHashOverhead<typename Super::key_type>::value +
sizeof(typename Super::value_type);
auto bc = this->bucket_count();
return (bc == 1 ? 0 : bc) * sizeof(typename Super::pointer) +
this->size() * nodeSize;
}
};
} // namespace detail
} // namespace f14
template <typename K, typename M, typename H, typename E, typename A>
class F14ValueMap : public f14::detail::F14BasicMap<K, M, H, E, A> {
using Super = f14::detail::F14BasicMap<K, M, H, E, A>;
public:
using Super::Super;
F14ValueMap() : Super() {}
};
template <typename K, typename M, typename H, typename E, typename A>
class F14NodeMap : public std::unordered_map<K, M, H, E, A> {
using Super = std::unordered_map<K, M, H, E, A>;
class F14NodeMap : public f14::detail::F14BasicMap<K, M, H, E, A> {
using Super = f14::detail::F14BasicMap<K, M, H, E, A>;
public:
using Super::Super;
......@@ -63,8 +94,8 @@ class F14NodeMap : public std::unordered_map<K, M, H, E, A> {
};
template <typename K, typename M, typename H, typename E, typename A>
class F14VectorMap : public std::unordered_map<K, M, H, E, A> {
using Super = std::unordered_map<K, M, H, E, A>;
class F14VectorMap : public f14::detail::F14BasicMap<K, M, H, E, A> {
using Super = f14::detail::F14BasicMap<K, M, H, E, A>;
public:
using Super::Super;
......
......@@ -15,6 +15,8 @@
*/
#include <folly/container/F14Map.h>
#include <folly/Conv.h>
#include <folly/container/test/F14TestUtil.h>
#include <folly/portability/GTest.h>
......@@ -44,6 +46,40 @@ TEST(F14Map, customSwap) {
testCustomSwap<folly::F14FastMap>();
}
namespace {
template <
template <typename, typename, typename, typename, typename> class TMap,
typename K,
typename V>
void testAllocatedMemorySize() {
using namespace folly::f14;
using A = SwapTrackingAlloc<std::pair<const K, V>>;
A::resetTracking();
TMap<K, V, DefaultHasher<K>, DefaultKeyEqual<K>, A> m;
EXPECT_EQ(A::getAllocatedMemorySize(), m.getAllocatedMemorySize());
for (size_t i = 0; i < 1; ++i) {
m.insert(std::make_pair(folly::to<K>(i), V{}));
EXPECT_EQ(A::getAllocatedMemorySize(), m.getAllocatedMemorySize());
}
}
template <typename K, typename V>
void runAllocatedMemorySizeTest() {
testAllocatedMemorySize<folly::F14ValueMap, K, V>();
testAllocatedMemorySize<folly::F14NodeMap, K, V>();
testAllocatedMemorySize<folly::F14VectorMap, K, V>();
testAllocatedMemorySize<folly::F14FastMap, K, V>();
}
} // namespace
TEST(F14Map, getAllocatedMemorySize) {
runAllocatedMemorySizeTest<int, int>();
runAllocatedMemorySizeTest<std::string, int>();
runAllocatedMemorySizeTest<std::string, std::string>();
}
///////////////////////////////////
#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
///////////////////////////////////
......
......@@ -309,6 +309,8 @@ std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) {
return xo;
}
thread_local size_t allocatedMemorySize{0};
template <class T>
class SwapTrackingAlloc {
public:
......@@ -349,10 +351,20 @@ class SwapTrackingAlloc {
return *this;
}
static size_t getAllocatedMemorySize() {
return allocatedMemorySize;
}
static void resetTracking() {
allocatedMemorySize = 0;
}
T* allocate(size_t n) {
allocatedMemorySize += n * sizeof(T);
return a_.allocate(n);
}
void deallocate(T* p, size_t n) {
allocatedMemorySize -= n * sizeof(T);
a_.deallocate(p, n);
}
......
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