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

Unified Diff: base/trace_event/memory_usage_estimators.h

Issue 2382443006: Sync MDP: implement MemoryDumpProvider
Patch Set: Created 4 years, 3 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 | components/sync/BUILD.gn » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/trace_event/memory_usage_estimators.h
diff --git a/base/trace_event/memory_usage_estimators.h b/base/trace_event/memory_usage_estimators.h
new file mode 100644
index 0000000000000000000000000000000000000000..f49094f0b19e6cac1db5035f275d77707b094e65
--- /dev/null
+++ b/base/trace_event/memory_usage_estimators.h
@@ -0,0 +1,193 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATORS_H_
+#define BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATORS_H_
+
+#include <memory>
+#include <set>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <vector>
+
+#include "base/strings/string16.h"
+
+namespace base {
+namespace trace_event {
+
+inline size_t EstimateMemoryUsage(const std::string& string) {
+#if defined(__GLIBCXX__) && _GLIBCXX_USE_CXX11_ABI == 0
+ // libstdc++ with COW std::string - each string allocates a header
+ // (see std::basic_string::_Rep_base). We don't take into account
+ // number of references, but we do handle 'empty string' case.
+ struct _Rep_base {
+ std::basic_string::size_type length;
+ std::basic_string::size_type capacity;
+ int refcount;
+ };
+ static const char* empty_cstr = nullptr;
+ if (!empty_cstr) empty_cstr = std::string().c_str();
+ return (string.c_str() == empty_cstr) ?
+ 0 :
+ sizeof(_Rep_base) + (string.capacity() + 1);
+#else
+ const char* cstr = string.c_str();
+ const char* inline_cstr = reinterpret_cast<const char*>(&string);
+ if (cstr >= inline_cstr && cstr < inline_cstr + sizeof(string)) {
+ // Inline string
+ return 0;
+ }
+ return string.capacity();
+#endif
+}
+
+// TODO(dskiba): EstimateMemoryUsage(std::basic_string<T>)
+inline size_t EstimateMemoryUsage(const base::string16& string) {
+#if defined(__GLIBCXX__) && _GLIBCXX_USE_CXX11_ABI == 0
+ // See comment in EstimateMemoryUsage(std::string).
+ static const char16* empty_cstr = nullptr;
+ if (!empty_cstr) empty_cstr = base::string16().c_str();
+ return (string.c_str() == empty_cstr) ?
+ 0 :
+ 3 * sizeof(size_t) + (string.capacity() + 1) * sizeof(char16);
+#else
+ const char* cstr = reinterpret_cast<const char*>(string.c_str());
+ const char* inline_cstr = reinterpret_cast<const char*>(&string);
+ if (cstr >= inline_cstr && cstr < inline_cstr + sizeof(string)) {
+ // Inline string
+ return 0;
+ }
+ return string.capacity() * sizeof(char16);
+#endif
+}
+
+template <class T>
+typename std::enable_if<
+ std::is_arithmetic<T>::value || std::is_enum<T>::value,
+ size_t>::type
+EstimateMemoryUsage(T) { return 0; }
+
+template <class T>
+auto EstimateMemoryUsage(const T& object) ->
+ decltype(object.EstimateMemoryUsage()) {
+ static_assert(std::is_same<decltype(object.EstimateMemoryUsage()),
+ size_t>::value,
+ "EstimateMemoryUsage() must return size_t");
+ return object.EstimateMemoryUsage();
+}
+
+// Any template that recursively calls EstimateMemoryUsage() should be
+// declared here first.
+
+template <class T>
+size_t EstimateMemoryUsage(const std::unique_ptr<T>& ptr);
+
+template <class F, class S>
+size_t EstimateMemoryUsage(const std::pair<F, S>& pair);
+
+template <class T, size_t N>
+size_t EstimateMemoryUsage(T (&array)[N]);
+
+template <class T, class A>
+size_t EstimateMemoryUsage(const std::vector<T, A>& vector);
+
+template <class T, class C, class A>
+size_t EstimateMemoryUsage(const std::set<T, C, A>& set);
+
+template <class K, class V, class H, class KE, class A>
+size_t EstimateMemoryUsage(
+ const std::unordered_map<K, V, H, KE, A>& map);
+
+// Definitions
+
+template <class T>
+size_t InternalEstimateItemMemoryUsage(T* pointer) {
+ // By default pointers treated as not owning
+ return 0;
+}
+
+template <class T>
+size_t InternalEstimateItemMemoryUsage(const T& value) {
+ return EstimateMemoryUsage(value);
+}
+
+template <class T>
+size_t EstimateMemoryUsage(const std::unique_ptr<T>& ptr) {
+ return ptr ? (sizeof(T) + EstimateMemoryUsage(*ptr)) : 0;
+}
+
+template <class F, class S>
+size_t EstimateMemoryUsage(const std::pair<F, S>& pair) {
+ return EstimateMemoryUsage(pair.first) +
+ EstimateMemoryUsage(pair.second);
+}
+
+template <class T, size_t N>
+size_t EstimateMemoryUsage(T (&array)[N]) {
+ size_t memory_usage = 0;
+ for (const auto& item: array) {
+ memory_usage += EstimateMemoryUsage(item);
+ }
+ return memory_usage;
+}
+
+template <class T, class A>
+size_t EstimateMemoryUsage(const std::vector<T, A>& vector) {
+ size_t memory_usage = vector.capacity() * sizeof(T);
+ for (const auto& element: vector) {
+ memory_usage += EstimateMemoryUsage(element);
+ }
+ return memory_usage;
+}
+
+template <class T, class C, class A>
+size_t EstimateMemoryUsage(const std::set<T, C, A>& set) {
+ // TODO(dskiba): revisit, likely not accurate enough
+ size_t memory_usage = set.size() * sizeof(T);
+ for (const auto& element: set) {
+ memory_usage += EstimateMemoryUsage(element);
+ }
+ return memory_usage;
+}
+
+template <class K, class V, class H, class KE, class A>
+size_t InternalEstimateShallowMemoryUsage(
+ const std::unordered_map<K, V, H, KE, A>& map) {
+ struct Node {
+ typename std::unordered_map<K, V, H, KE, A>::value_type value;
+ Node* next;
+ Node* prev;
+ };
+ using Bucket = Node*;
+ return map.bucket_count() * sizeof(Bucket) + map.size() * sizeof(Node);
+}
+
+template <class K, class V, class H, class KE, class A>
+size_t EstimateMemoryUsage(
+ const std::unordered_map<K, V, H, KE, A>& map) {
+ size_t memory_usage = InternalEstimateShallowMemoryUsage(map);
+ for (const auto& item: map) {
+ memory_usage += InternalEstimateItemMemoryUsage(item.first) +
+ InternalEstimateItemMemoryUsage(item.second);
+ }
+ return memory_usage;
+}
+
+template <class K, class V, class H, class KE, class A, class Estimator>
+size_t EstimateMemoryUsage(
+ const std::unordered_map<K, V, H, KE, A>& map,
+ Estimator estimator) {
+ size_t memory_usage = InternalEstimateShallowMemoryUsage(map);
+ for (const auto& item: map) {
+ memory_usage += estimator(item.first) +
+ estimator(item.second);
+ }
+ return memory_usage;
+}
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATORS_H_
« no previous file with comments | « no previous file | components/sync/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698