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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | base/trace_event/memory_usage_estimator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_ 5 #ifndef BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_
6 #define BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_ 6 #define BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <array> 10 #include <array>
11 #include <deque>
11 #include <list> 12 #include <list>
12 #include <map> 13 #include <map>
13 #include <memory> 14 #include <memory>
15 #include <queue>
14 #include <set> 16 #include <set>
17 #include <stack>
15 #include <string> 18 #include <string>
16 #include <type_traits> 19 #include <type_traits>
17 #include <unordered_map> 20 #include <unordered_map>
18 #include <unordered_set> 21 #include <unordered_set>
19 #include <vector> 22 #include <vector>
20 23
21 #include "base/base_export.h" 24 #include "base/base_export.h"
22 #include "base/strings/string16.h" 25 #include "base/strings/string16.h"
23 #include "base/template_util.h" 26 #include "base/template_util.h"
24 27
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 128
126 template <class T, class H, class KE, class A> 129 template <class T, class H, class KE, class A>
127 size_t EstimateMemoryUsage(const std::unordered_multiset<T, H, KE, A>& set); 130 size_t EstimateMemoryUsage(const std::unordered_multiset<T, H, KE, A>& set);
128 131
129 template <class K, class V, class H, class KE, class A> 132 template <class K, class V, class H, class KE, class A>
130 size_t EstimateMemoryUsage(const std::unordered_map<K, V, H, KE, A>& map); 133 size_t EstimateMemoryUsage(const std::unordered_map<K, V, H, KE, A>& map);
131 134
132 template <class K, class V, class H, class KE, class A> 135 template <class K, class V, class H, class KE, class A>
133 size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map); 136 size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map);
134 137
138 template <class T, class A>
139 size_t EstimateMemoryUsage(const std::deque<T, A>& deque);
140
141 template <class T, class C>
142 size_t EstimateMemoryUsage(const std::queue<T, C>& queue);
143
144 template <class T, class C>
145 size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue);
146
147 template <class T, class C>
148 size_t EstimateMemoryUsage(const std::stack<T, C>& stack);
149
135 // TODO(dskiba): 150 // TODO(dskiba):
136 // std::forward_list 151 // std::forward_list
137 // std::deque
138 // std::queue
139 // std::stack
140 // std::queue
141 // std::priority_queue
142 152
143 // Definitions 153 // Definitions
144 154
145 namespace internal { 155 namespace internal {
146 156
147 // HasEMU<T>::value is true iff EstimateMemoryUsage(T) is available. 157 // HasEMU<T>::value is true iff EstimateMemoryUsage(T) is available.
148 // (This is the default version, which is false.) 158 // (This is the default version, which is false.)
149 template <class T, class X = void> 159 template <class T, class X = void>
150 struct HasEMU : std::false_type {}; 160 struct HasEMU : std::false_type {};
151 161
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 }; 200 };
191 201
192 template <class T> 202 template <class T>
193 struct EMUCaller< 203 struct EMUCaller<
194 T, 204 T,
195 typename std::enable_if<!HasEMU<T>::value && 205 typename std::enable_if<!HasEMU<T>::value &&
196 is_trivially_destructible<T>::value>::type> { 206 is_trivially_destructible<T>::value>::type> {
197 static size_t Call(const T& value) { return 0; } 207 static size_t Call(const T& value) { return 0; }
198 }; 208 };
199 209
210 // Returns reference to the underlying container of a container adapter.
211 // Works for std::stack, std::queue and std::priority_queue.
212 template <class A>
213 const typename A::container_type& GetUnderlyingContainer(const A& adapter) {
214 struct ExposedAdapter : A {
215 using A::c;
216 };
217 return adapter.*&ExposedAdapter::c;
218 }
219
200 } // namespace internal 220 } // namespace internal
201 221
202 // Proxy that deducts T and calls EMUCaller<T>. 222 // Proxy that deducts T and calls EMUCaller<T>.
203 // To be used by EstimateMemoryUsage() implementations for containers. 223 // To be used by EstimateMemoryUsage() implementations for containers.
204 template <class T> 224 template <class T>
205 size_t EstimateItemMemoryUsage(const T& value) { 225 size_t EstimateItemMemoryUsage(const T& value) {
206 return internal::EMUCaller<T>::Call(value); 226 return internal::EMUCaller<T>::Call(value);
207 } 227 }
208 228
209 template <class I> 229 template <class I>
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 452
433 template <class K, class V, class H, class KE, class A> 453 template <class K, class V, class H, class KE, class A>
434 size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map) { 454 size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map) {
435 using value_type = 455 using value_type =
436 typename std::unordered_multimap<K, V, H, KE, A>::value_type; 456 typename std::unordered_multimap<K, V, H, KE, A>::value_type;
437 return EstimateHashMapMemoryUsage<value_type>(map.bucket_count(), 457 return EstimateHashMapMemoryUsage<value_type>(map.bucket_count(),
438 map.size()) + 458 map.size()) +
439 EstimateIterableMemoryUsage(map); 459 EstimateIterableMemoryUsage(map);
440 } 460 }
441 461
462 // std::deque
463
464 template <class T, class A>
465 size_t EstimateMemoryUsage(const std::deque<T, A>& deque) {
466 // Since std::deque implementations are wildly different
467 // (see crbug.com/674287), we can't have one "good enough"
468 // way to estimate.
469
470 // kBlockSize - minimum size of a block, in bytes
471 // kMinBlockLength - number of elements in a block
472 // if sizeof(T) > kBlockSize
473 #if defined(_LIBCPP_VERSION)
474 size_t kBlockSize = 4096;
475 size_t kMinBlockLength = 16;
476 #elif defined(__GLIBCXX__)
477 size_t kBlockSize = 512;
478 size_t kMinBlockLength = 1;
479 #elif defined(_MSC_VER)
480 size_t kBlockSize = 16;
481 size_t kMinBlockLength = 1;
482 #else
483 size_t kBlockSize = 0;
484 size_t kMinBlockLength = 1;
485 #endif
486
487 size_t block_length =
488 (sizeof(T) > kBlockSize) ? kMinBlockLength : kBlockSize / sizeof(T);
489
490 size_t blocks = (deque.size() + block_length - 1) / block_length;
491
492 #if defined(__GLIBCXX__)
493 // libstdc++: deque always has at least one block
494 if (!blocks)
495 blocks = 1;
496 #endif
497
498 #if defined(_LIBCPP_VERSION)
499 // libc++: deque keeps at most two blocks when it shrinks,
500 // so even if the size is zero, deque might be holding up
501 // to 4096 * 2 bytes. One way to know whether deque has
502 // ever allocated (and hence has 1 or 2 blocks) is to check
503 // iterator's pointer. Non-zero value means that deque has
504 // at least one block.
505 if (!blocks && deque.begin().operator->())
506 blocks = 1;
507 #endif
508
509 return (blocks * block_length * sizeof(T)) +
510 EstimateIterableMemoryUsage(deque);
511 }
512
513 // Container adapters
514
515 template <class T, class C>
516 size_t EstimateMemoryUsage(const std::queue<T, C>& queue) {
517 return EstimateMemoryUsage(internal::GetUnderlyingContainer(queue));
518 }
519
520 template <class T, class C>
521 size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue) {
522 return EstimateMemoryUsage(internal::GetUnderlyingContainer(queue));
523 }
524
525 template <class T, class C>
526 size_t EstimateMemoryUsage(const std::stack<T, C>& stack) {
527 return EstimateMemoryUsage(internal::GetUnderlyingContainer(stack));
528 }
529
442 } // namespace trace_event 530 } // namespace trace_event
443 } // namespace base 531 } // namespace base
444 532
445 #endif // BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_ 533 #endif // BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_
OLDNEW
« 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