Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1778)

Unified Diff: base/trace_event/memory_usage_estimator.h

Issue 2676043002: [memory-infra] Add EstimateMemoryUsage() for deque and friends. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/trace_event/memory_usage_estimator_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/trace_event/memory_usage_estimator.h
diff --git a/base/trace_event/memory_usage_estimator.h b/base/trace_event/memory_usage_estimator.h
index 4f230c7b3890911c73c50d786a78514ac6ada83d..1f4132bdcb2dcf29cd0396fe7c2ac691b0e6769b 100644
--- a/base/trace_event/memory_usage_estimator.h
+++ b/base/trace_event/memory_usage_estimator.h
@@ -8,10 +8,13 @@
#include <stdint.h>
#include <array>
+#include <deque>
#include <list>
#include <map>
#include <memory>
+#include <queue>
#include <set>
+#include <stack>
#include <string>
#include <type_traits>
#include <unordered_map>
@@ -132,13 +135,20 @@ size_t EstimateMemoryUsage(const std::unordered_map<K, V, H, KE, A>& map);
template <class K, class V, class H, class KE, class A>
size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map);
+template <class T, class A>
+size_t EstimateMemoryUsage(const std::deque<T, A>& deque);
+
+template <class T, class C>
+size_t EstimateMemoryUsage(const std::queue<T, C>& queue);
+
+template <class T, class C>
+size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue);
+
+template <class T, class C>
+size_t EstimateMemoryUsage(const std::stack<T, C>& stack);
+
// TODO(dskiba):
// std::forward_list
-// std::deque
-// std::queue
-// std::stack
-// std::queue
-// std::priority_queue
// Definitions
@@ -197,6 +207,16 @@ struct EMUCaller<
static size_t Call(const T& value) { return 0; }
};
+// Returns reference to the underlying container of a container adapter.
+// Works for std::stack, std::queue and std::priority_queue.
+template <class A>
+const typename A::container_type& GetUnderlyingContainer(const A& adapter) {
+ struct ExposedAdapter : A {
+ using A::c;
+ };
+ return adapter.*&ExposedAdapter::c;
+}
+
} // namespace internal
// Proxy that deducts T and calls EMUCaller<T>.
@@ -439,6 +459,74 @@ size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map) {
EstimateIterableMemoryUsage(map);
}
+// std::deque
+
+template <class T, class A>
+size_t EstimateMemoryUsage(const std::deque<T, A>& deque) {
+// Since std::deque implementations are wildly different
+// (see crbug.com/674287), we can't have one "good enough"
+// way to estimate.
+
+// kBlockSize - minimum size of a block, in bytes
+// kMinBlockLength - number of elements in a block
+// if sizeof(T) > kBlockSize
+#if defined(_LIBCPP_VERSION)
+ size_t kBlockSize = 4096;
+ size_t kMinBlockLength = 16;
+#elif defined(__GLIBCXX__)
+ size_t kBlockSize = 512;
+ size_t kMinBlockLength = 1;
+#elif defined(_MSC_VER)
+ size_t kBlockSize = 16;
+ size_t kMinBlockLength = 1;
+#else
+ size_t kBlockSize = 0;
+ size_t kMinBlockLength = 1;
+#endif
+
+ size_t block_length =
+ (sizeof(T) > kBlockSize) ? kMinBlockLength : kBlockSize / sizeof(T);
+
+ size_t blocks = (deque.size() + block_length - 1) / block_length;
+
+#if defined(__GLIBCXX__)
+ // libstdc++: deque always has at least one block
+ if (!blocks)
+ blocks = 1;
+#endif
+
+#if defined(_LIBCPP_VERSION)
+ // libc++: deque keeps at most two blocks when it shrinks,
+ // so even if the size is zero, deque might be holding up
+ // to 4096 * 2 bytes. One way to know whether deque has
+ // ever allocated (and hence has 1 or 2 blocks) is to check
+ // iterator's pointer. Non-zero value means that deque has
+ // at least one block.
+ if (!blocks && deque.begin().operator->())
+ blocks = 1;
+#endif
+
+ return (blocks * block_length * sizeof(T)) +
+ EstimateIterableMemoryUsage(deque);
+}
+
+// Container adapters
+
+template <class T, class C>
+size_t EstimateMemoryUsage(const std::queue<T, C>& queue) {
+ return EstimateMemoryUsage(internal::GetUnderlyingContainer(queue));
+}
+
+template <class T, class C>
+size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue) {
+ return EstimateMemoryUsage(internal::GetUnderlyingContainer(queue));
+}
+
+template <class T, class C>
+size_t EstimateMemoryUsage(const std::stack<T, C>& stack) {
+ return EstimateMemoryUsage(internal::GetUnderlyingContainer(stack));
+}
+
} // namespace trace_event
} // namespace base
« no previous file with comments | « no previous file | base/trace_event/memory_usage_estimator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698