Index: content/common/discardable_shared_memory_heap.cc |
diff --git a/content/common/discardable_shared_memory_heap.cc b/content/common/discardable_shared_memory_heap.cc |
index 36ee632255329506570831c90bc23287cad00580..4509d101a29456c206dd99938167fb91ced52176 100644 |
--- a/content/common/discardable_shared_memory_heap.cc |
+++ b/content/common/discardable_shared_memory_heap.cc |
@@ -6,11 +6,19 @@ |
#include <algorithm> |
+#include "base/atomic_sequence_num.h" |
#include "base/memory/discardable_shared_memory.h" |
+#include "base/strings/stringprintf.h" |
namespace content { |
namespace { |
+const char kMemoryAllocatorHeapNamePrefix[] = "segment_%zu"; |
+const char kMemoryAllocatorName[] = "discardable"; |
+ |
+// Global atomic to generate unique discardable shared memory IDs. |
+base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id; |
+ |
bool IsPowerOfTwo(size_t x) { |
return (x & (x - 1)) == 0; |
} |
@@ -35,10 +43,12 @@ DiscardableSharedMemoryHeap::ScopedMemorySegment::ScopedMemorySegment( |
DiscardableSharedMemoryHeap* heap, |
scoped_ptr<base::DiscardableSharedMemory> shared_memory, |
size_t size, |
+ DiscardableSharedMemoryId id, |
const base::Closure& deleted_callback) |
: heap_(heap), |
shared_memory_(shared_memory.Pass()), |
size_(size), |
+ id_(id), |
deleted_callback_(deleted_callback) { |
} |
@@ -55,6 +65,11 @@ bool DiscardableSharedMemoryHeap::ScopedMemorySegment::IsResident() const { |
return heap_->IsMemoryResident(shared_memory_.get()); |
} |
+void DiscardableSharedMemoryHeap::ScopedMemorySegment::DumpMemoryStatisticsInto( |
+ base::trace_event::ProcessMemoryDump* pmd) const { |
+ heap_->DumpSegmentStatistics(shared_memory_.get(), size_, id_, pmd); |
+} |
+ |
DiscardableSharedMemoryHeap::DiscardableSharedMemoryHeap(size_t block_size) |
: block_size_(block_size), num_blocks_(0), num_free_blocks_(0) { |
DCHECK_NE(block_size_, 0u); |
@@ -92,9 +107,12 @@ scoped_ptr<DiscardableSharedMemoryHeap::Span> DiscardableSharedMemoryHeap::Grow( |
num_blocks_ += span->length_; |
+ DiscardableSharedMemoryId new_id = |
+ g_next_discardable_shared_memory_id.GetNext(); |
reveman
2015/04/27 13:28:11
Please pass the ID as a parameter instead. ChildDi
ssid
2015/04/27 14:27:01
Oh i dint realize, thanks.
|
+ |
// Start tracking if segment is resident by adding it to |memory_segments_|. |
- memory_segments_.push_back(new ScopedMemorySegment(this, shared_memory.Pass(), |
- size, deleted_callback)); |
+ memory_segments_.push_back(new ScopedMemorySegment( |
+ this, shared_memory.Pass(), size, new_id, deleted_callback)); |
return span.Pass(); |
} |
@@ -212,6 +230,15 @@ size_t DiscardableSharedMemoryHeap::GetSizeOfFreeLists() const { |
return num_free_blocks_ * block_size_; |
} |
+bool DiscardableSharedMemoryHeap::DumpMemoryStatisticsInto( |
+ base::trace_event::ProcessMemoryDump* pmd) { |
+ std::for_each(memory_segments_.begin(), memory_segments_.end(), |
+ [pmd](const ScopedMemorySegment* segment) { |
+ segment->DumpMemoryStatisticsInto(pmd); |
+ }); |
+ return true; |
+} |
+ |
void DiscardableSharedMemoryHeap::InsertIntoFreeList( |
scoped_ptr<DiscardableSharedMemoryHeap::Span> span) { |
DCHECK(!IsInFreeList(span.get())); |
@@ -316,4 +343,35 @@ void DiscardableSharedMemoryHeap::ReleaseMemory( |
} |
} |
+void DiscardableSharedMemoryHeap::DumpSegmentStatistics( |
+ const base::DiscardableSharedMemory* shared_memory, |
+ size_t segment_size, |
reveman
2015/04/27 13:28:11
nit: s/segment_size/size/ to be consistent with Re
ssid
2015/04/27 14:27:01
Done.
|
+ DiscardableSharedMemoryId id, |
+ base::trace_event::ProcessMemoryDump* pmd) { |
+ std::string segment_id = |
reveman
2015/04/27 13:28:11
nit: maybe heap_name instead
ssid
2015/04/27 14:27:01
Done.
|
+ base::StringPrintf(kMemoryAllocatorHeapNamePrefix, id); |
+ base::trace_event::MemoryAllocatorDump* segment_dump = |
reveman
2015/04/27 13:28:11
fyi, "dump" is enough if the cleans things up, up
ssid
2015/04/27 14:27:01
Done.
|
+ pmd->CreateAllocatorDump(kMemoryAllocatorName, segment_id.c_str()); |
reveman
2015/04/27 13:28:11
What if this fails? Looks like other dump provider
ssid
2015/04/27 14:27:01
The check is unnecessary, will be removed in other
reveman
2015/04/27 15:08:58
Acknowledged.
|
+ |
+ size_t allocated_objects_count = 0; |
+ size_t allocated_objects_size_in_bytes = 0; |
+ size_t offset = |
+ reinterpret_cast<size_t>(shared_memory->memory()) / block_size_; |
+ size_t end = offset + segment_size / block_size_; |
+ while (offset < end) { |
+ Span* span = spans_[offset]; |
+ if (!IsInFreeList(span)) { |
+ allocated_objects_count++; |
+ allocated_objects_size_in_bytes += span->length_; |
+ } |
+ offset += span->length_; |
+ } |
+ |
+ segment_dump->set_physical_size_in_bytes(static_cast<uint64>(segment_size)); |
+ segment_dump->set_allocated_objects_count( |
+ static_cast<uint64>(allocated_objects_count)); |
+ segment_dump->set_allocated_objects_size_in_bytes( |
+ static_cast<uint64>(allocated_objects_size_in_bytes)); |
reveman
2015/04/27 13:28:11
are these static_casts really needed?
ssid
2015/04/27 14:27:01
yes, since windows build gives conversion error fr
reveman
2015/04/27 15:08:58
hm, I would expect size_t to uint64 to always be o
|
+} |
+ |
} // namespace content |