Commit ee150027 authored by Benoît Lizé's avatar Benoît Lizé Committed by Commit Bot

blink/bindings: Record memory metrics for foreground string parking.

Memory metrics for ParkableStrings are only reported for background
compression. This adds reporting for foreground compression as well, 5 minutes
after a renderer starts tracking its first parkable string.

Bug: 924164
Change-Id: Iac04e86101e132fa9d67c6cfd25b16e2bce89fb9
Reviewed-on: https://chromium-review.googlesource.com/c/1474663Reviewed-by: default avatarBrian White <bcwhite@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Benoit L <lizeb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#633781}
parent 7af418f0
...@@ -51,9 +51,12 @@ class OnPurgeMemoryListener : public GarbageCollected<OnPurgeMemoryListener>, ...@@ -51,9 +51,12 @@ class OnPurgeMemoryListener : public GarbageCollected<OnPurgeMemoryListener>,
} }
}; };
using UnparkedMap =
HashMap<StringImpl*, ParkableStringImpl*, PtrHash<StringImpl>>;
using ParkedSet = HashSet<ParkableStringImpl*, PtrHash<ParkableStringImpl>>;
Vector<ParkableStringImpl*> GetUnparkedStrings( Vector<ParkableStringImpl*> GetUnparkedStrings(
const HashMap<StringImpl*, ParkableStringImpl*, PtrHash<StringImpl>>& const UnparkedMap& unparked_strings) {
unparked_strings) {
WTF::Vector<ParkableStringImpl*> unparked; WTF::Vector<ParkableStringImpl*> unparked;
unparked.ReserveCapacity(unparked_strings.size()); unparked.ReserveCapacity(unparked_strings.size());
for (ParkableStringImpl* str : unparked_strings.Values()) for (ParkableStringImpl* str : unparked_strings.Values())
...@@ -62,6 +65,68 @@ Vector<ParkableStringImpl*> GetUnparkedStrings( ...@@ -62,6 +65,68 @@ Vector<ParkableStringImpl*> GetUnparkedStrings(
return unparked; return unparked;
} }
struct Statistics {
size_t original_size;
size_t uncompressed_size;
size_t compressed_original_size;
size_t compressed_size;
size_t metadata_size;
size_t overhead_size;
size_t total_size;
int64_t savings_size;
};
Statistics ComputeStatistics(const UnparkedMap& unparked,
const ParkedSet& parked) {
Statistics stats = {};
for (ParkableStringImpl* str : unparked.Values()) {
size_t size = str->CharactersSizeInBytes();
stats.original_size += size;
stats.uncompressed_size += size;
stats.metadata_size += sizeof(ParkableStringImpl);
if (str->has_compressed_data())
stats.overhead_size += str->compressed_size();
}
for (ParkableStringImpl* str : parked) {
size_t size = str->CharactersSizeInBytes();
stats.compressed_original_size += size;
stats.original_size += size;
stats.compressed_size += str->compressed_size();
stats.metadata_size += sizeof(ParkableStringImpl);
}
stats.total_size = stats.uncompressed_size + stats.compressed_size +
stats.metadata_size + stats.overhead_size;
size_t memory_footprint = stats.compressed_size + stats.uncompressed_size +
stats.metadata_size + stats.overhead_size;
stats.savings_size =
stats.original_size - static_cast<int64_t>(memory_footprint);
return stats;
}
void RecordMemoryStatistics(const Statistics& stats,
const std::string& suffix) {
base::UmaHistogramCounts100000("Memory.ParkableString.TotalSizeKb" + suffix,
stats.original_size / 1000);
base::UmaHistogramCounts100000(
"Memory.ParkableString.CompressedSizeKb" + suffix,
stats.compressed_size / 1000);
size_t savings = stats.compressed_original_size - stats.compressed_size;
base::UmaHistogramCounts100000("Memory.ParkableString.SavingsKb" + suffix,
savings / 1000);
if (stats.compressed_original_size != 0) {
size_t ratio_percentage =
(100 * stats.compressed_size) / stats.compressed_original_size;
base::UmaHistogramPercentage(
"Memory.ParkableString.CompressionRatio" + suffix, ratio_percentage);
}
}
} // namespace } // namespace
// static // static
...@@ -148,41 +213,17 @@ bool ParkableStringManager::OnMemoryDump( ...@@ -148,41 +213,17 @@ bool ParkableStringManager::OnMemoryDump(
base::trace_event::MemoryAllocatorDump* dump = base::trace_event::MemoryAllocatorDump* dump =
pmd->CreateAllocatorDump("parkable_strings"); pmd->CreateAllocatorDump("parkable_strings");
size_t original_size = 0; Statistics stats = ComputeStatistics(unparked_strings_, parked_strings_);
size_t uncompressed_size = 0;
size_t compressed_size = 0;
size_t metadata_size = 0;
size_t overhead_size = 0;
for (ParkableStringImpl* str : unparked_strings_.Values()) {
original_size += str->CharactersSizeInBytes();
uncompressed_size += str->CharactersSizeInBytes();
metadata_size += sizeof(ParkableStringImpl);
if (str->has_compressed_data())
overhead_size += str->compressed_size();
}
for (ParkableStringImpl* str : parked_strings_) {
original_size += str->CharactersSizeInBytes();
compressed_size += str->compressed_size();
metadata_size += sizeof(ParkableStringImpl);
}
size_t total_size = dump->AddScalar("size", "bytes", stats.total_size);
uncompressed_size + compressed_size + metadata_size + overhead_size; dump->AddScalar("original_size", "bytes", stats.original_size);
size_t memory_footprint = dump->AddScalar("uncompressed_size", "bytes", stats.uncompressed_size);
compressed_size + uncompressed_size + metadata_size + overhead_size; dump->AddScalar("compressed_size", "bytes", stats.compressed_size);
dump->AddScalar("metadata_size", "bytes", stats.metadata_size);
dump->AddScalar("overhead_size", "bytes", stats.overhead_size);
// Has to be uint64_t. // Has to be uint64_t.
size_t savings_size = dump->AddScalar("savings_size", "bytes",
original_size > memory_footprint ? original_size - memory_footprint : 0; stats.savings_size > 0 ? stats.savings_size : 0);
dump->AddScalar("size", "bytes", total_size);
dump->AddScalar("original_size", "bytes", original_size);
dump->AddScalar("uncompressed_size", "bytes", uncompressed_size);
dump->AddScalar("compressed_size", "bytes", compressed_size);
dump->AddScalar("metadata_size", "bytes", metadata_size);
dump->AddScalar("overhead_size", "bytes", overhead_size);
dump->AddScalar("savings_size", "bytes", savings_size);
pmd->AddSuballocation(dump->guid(), pmd->AddSuballocation(dump->guid(),
WTF::Partitions::kAllocatedObjectPoolName); WTF::Partitions::kAllocatedObjectPoolName);
...@@ -229,7 +270,7 @@ scoped_refptr<ParkableStringImpl> ParkableStringManager::Add( ...@@ -229,7 +270,7 @@ scoped_refptr<ParkableStringImpl> ParkableStringManager::Add(
DCHECK(task_runner); DCHECK(task_runner);
task_runner->PostDelayedTask( task_runner->PostDelayedTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&ParkableStringManager::RecordUnparkingCpuCost, base::BindOnce(&ParkableStringManager::RecordStatisticsAfter5Minutes,
base::Unretained(this)), base::Unretained(this)),
base::TimeDelta::FromMinutes(5)); base::TimeDelta::FromMinutes(5));
has_posted_unparking_time_accounting_task_ = true; has_posted_unparking_time_accounting_task_ = true;
...@@ -342,36 +383,15 @@ void ParkableStringManager::DropStringsWithCompressedDataAndRecordStatistics() { ...@@ -342,36 +383,15 @@ void ParkableStringManager::DropStringsWithCompressedDataAndRecordStatistics() {
ParkAllIfRendererBackgrounded( ParkAllIfRendererBackgrounded(
ParkableStringImpl::ParkingMode::kIfCompressedDataExists); ParkableStringImpl::ParkingMode::kIfCompressedDataExists);
size_t total_size = 0, total_before_compression_size = 0; Statistics stats = ComputeStatistics(unparked_strings_, parked_strings_);
size_t total_compressed_size = 0; RecordMemoryStatistics(stats, "");
for (ParkableStringImpl* str : parked_strings_) {
size_t size = str->CharactersSizeInBytes();
total_size += size;
total_before_compression_size += size;
total_compressed_size += str->compressed_size();
}
for (ParkableStringImpl* str : unparked_strings_.Values())
total_size += str->CharactersSizeInBytes();
UMA_HISTOGRAM_COUNTS_100000("Memory.ParkableString.TotalSizeKb",
total_size / 1000);
UMA_HISTOGRAM_COUNTS_100000("Memory.ParkableString.CompressedSizeKb",
total_compressed_size / 1000);
size_t savings = total_before_compression_size - total_compressed_size;
UMA_HISTOGRAM_COUNTS_100000("Memory.ParkableString.SavingsKb",
savings / 1000);
if (total_before_compression_size != 0) {
size_t ratio_percentage =
(100 * total_compressed_size) / total_before_compression_size;
UMA_HISTOGRAM_PERCENTAGE("Memory.ParkableString.CompressionRatio",
ratio_percentage);
}
} }
void ParkableStringManager::RecordUnparkingCpuCost() const { void ParkableStringManager::RecordStatisticsAfter5Minutes() const {
base::UmaHistogramTimes("Memory.ParkableString.MainThreadTime.5min", base::UmaHistogramTimes("Memory.ParkableString.MainThreadTime.5min",
total_unparking_time_); total_unparking_time_);
Statistics stats = ComputeStatistics(unparked_strings_, parked_strings_);
RecordMemoryStatistics(stats, ".5min");
} }
void ParkableStringManager::AgeStringsAndPark() { void ParkableStringManager::AgeStringsAndPark() {
......
...@@ -83,7 +83,7 @@ class PLATFORM_EXPORT ParkableStringManager { ...@@ -83,7 +83,7 @@ class PLATFORM_EXPORT ParkableStringManager {
void ParkAll(ParkableStringImpl::ParkingMode mode); void ParkAll(ParkableStringImpl::ParkingMode mode);
void ParkAllIfRendererBackgrounded(ParkableStringImpl::ParkingMode mode); void ParkAllIfRendererBackgrounded(ParkableStringImpl::ParkingMode mode);
void DropStringsWithCompressedDataAndRecordStatistics(); void DropStringsWithCompressedDataAndRecordStatistics();
void RecordUnparkingCpuCost() const; void RecordStatisticsAfter5Minutes() const;
void AgeStringsAndPark(); void AgeStringsAndPark();
void ScheduleAgingTaskIfNeeded(); void ScheduleAgingTaskIfNeeded();
......
...@@ -916,7 +916,8 @@ TEST_F(ParkableStringForegroundParkingTest, ReportTotalUnparkingTime) { ...@@ -916,7 +916,8 @@ TEST_F(ParkableStringForegroundParkingTest, ReportTotalUnparkingTime) {
// Need to make the string really large, otherwise unparking takes less than // Need to make the string really large, otherwise unparking takes less than
// 1ms, and the 0 bucket is populated. // 1ms, and the 0 bucket is populated.
std::vector<char> data(5 * 1000 * 1000, 'a'); const size_t original_size = 5 * 1000 * 1000;
std::vector<char> data(original_size, 'a');
ParkableString parkable(String(data.data(), data.size()).ReleaseImpl()); ParkableString parkable(String(data.data(), data.size()).ReleaseImpl());
ParkAndWait(parkable); ParkAndWait(parkable);
...@@ -926,12 +927,25 @@ TEST_F(ParkableStringForegroundParkingTest, ReportTotalUnparkingTime) { ...@@ -926,12 +927,25 @@ TEST_F(ParkableStringForegroundParkingTest, ReportTotalUnparkingTime) {
WaitForAging(); WaitForAging();
CheckOnlyCpuCostTaskRemains(); CheckOnlyCpuCostTaskRemains();
} }
const size_t compressed_size = parkable.Impl()->compressed_size();
scoped_task_environment_.FastForwardUntilNoTasksRemain(); scoped_task_environment_.FastForwardUntilNoTasksRemain();
histogram_tester.ExpectTotalCount("Memory.ParkableString.MainThreadTime.5min", histogram_tester.ExpectTotalCount("Memory.ParkableString.MainThreadTime.5min",
1); 1);
histogram_tester.ExpectBucketCount( histogram_tester.ExpectBucketCount(
"Memory.ParkableString.MainThreadTime.5min", 0, 0); "Memory.ParkableString.MainThreadTime.5min", 0, 0);
histogram_tester.ExpectUniqueSample("Memory.ParkableString.TotalSizeKb.5min",
original_size / 1000, 1);
histogram_tester.ExpectUniqueSample(
"Memory.ParkableString.CompressedSizeKb.5min", compressed_size / 1000, 1);
size_t expected_savings = original_size - compressed_size;
histogram_tester.ExpectUniqueSample("Memory.ParkableString.SavingsKb.5min",
expected_savings / 1000, 1);
histogram_tester.ExpectUniqueSample(
"Memory.ParkableString.CompressionRatio.5min",
100 * compressed_size / original_size, 1);
} }
} // namespace blink } // namespace blink
...@@ -52890,6 +52890,16 @@ uploading your change for review. ...@@ -52890,6 +52890,16 @@ uploading your change for review.
</summary> </summary>
</histogram> </histogram>
<histogram name="Memory.ParkableString.CompressionRatio.5min" units="%"
expires_after="2019-07-31">
<owner>lizeb@chromium.org</owner>
<summary>
Average compression ratio, 100 * compressed_size / initial_size, for all
compressed ParkableStrings. Recorded at the same time as
&quot;Memory.ParkableString.TotalSizeKb.5min&quot;.
</summary>
</histogram>
<histogram name="Memory.ParkableString.Decompression.Latency" <histogram name="Memory.ParkableString.Decompression.Latency"
units="microseconds"> units="microseconds">
<owner>lizeb@chromium.org</owner> <owner>lizeb@chromium.org</owner>
...@@ -52931,6 +52941,15 @@ uploading your change for review. ...@@ -52931,6 +52941,15 @@ uploading your change for review.
</summary> </summary>
</histogram> </histogram>
<histogram name="Memory.ParkableString.SavingsKb.5min" units="KB"
expires_after="2019-07-31">
<owner>lizeb@chromium.org</owner>
<summary>
Sum of memory saved by compression, in KB. Recorded at the same time as
&quot;Memory.ParkableString.TotalSizeKb.5min&quot;.
</summary>
</histogram>
<histogram name="Memory.ParkableString.TotalSizeKb" units="KB"> <histogram name="Memory.ParkableString.TotalSizeKb" units="KB">
<owner>lizeb@chromium.org</owner> <owner>lizeb@chromium.org</owner>
<summary> <summary>
...@@ -52940,6 +52959,16 @@ uploading your change for review. ...@@ -52940,6 +52959,16 @@ uploading your change for review.
</summary> </summary>
</histogram> </histogram>
<histogram name="Memory.ParkableString.TotalSizeKb.5min" units="KB"
expires_after="2019-07-31">
<owner>lizeb@chromium.org</owner>
<summary>
Total size of ParkableStrings assuming no compression, in KB. Recorded once,
5 minutes after the first ParkableString is added to a renderer, at the same
time as &quot;Memory.ParkableString.MainThreadTime.5min&quot;.
</summary>
</histogram>
<histogram name="Memory.PepperFlashPlugin" units="KB"> <histogram name="Memory.PepperFlashPlugin" units="KB">
<obsolete> <obsolete>
Deprecated 11/2017. No direct replacement. Deprecated 11/2017. No direct replacement.
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