| // Copyright 2018 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. |
| |
| #include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/macros.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "third_party/blink/public/platform/platform.h" |
| #include "third_party/blink/renderer/platform/bindings/parkable_string.h" |
| #include "third_party/blink/renderer/platform/scheduler/public/thread.h" |
| #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" |
| #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" |
| #include "third_party/blink/renderer/platform/wtf/wtf.h" |
| |
| namespace blink { |
| |
| ParkableStringManager& ParkableStringManager::Instance() { |
| DCHECK(IsMainThread()); |
| DEFINE_STATIC_LOCAL(ParkableStringManager, instance, ()); |
| return instance; |
| } |
| |
| ParkableStringManager::~ParkableStringManager() {} |
| |
| void ParkableStringManager::SetRendererBackgrounded(bool backgrounded) { |
| backgrounded_ = backgrounded; |
| |
| if (backgrounded_) { |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
| Platform::Current()->CurrentThread()->GetTaskRunner(); |
| task_runner->PostDelayedTask( |
| FROM_HERE, |
| base::BindOnce(&ParkableStringManager::ParkAllIfRendererBackgrounded, |
| base::Unretained(this)), |
| base::TimeDelta::FromSeconds(10)); |
| } |
| } |
| |
| bool ParkableStringManager::IsRendererBackgrounded() const { |
| return backgrounded_; |
| } |
| |
| // static |
| bool ParkableStringManager::ShouldPark(const StringImpl& string) { |
| // Don't attempt to park strings smaller than this size. |
| static constexpr unsigned int kSizeThreshold = 10000; |
| // TODO(lizeb): Consider parking non-main thread strings. |
| return string.length() > kSizeThreshold && IsMainThread(); |
| } |
| |
| scoped_refptr<ParkableStringImpl> ParkableStringManager::Add( |
| scoped_refptr<StringImpl>&& string) { |
| StringImpl* raw_ptr = string.get(); |
| auto it = table_.find(raw_ptr); |
| if (it != table_.end()) |
| return it->value; |
| |
| auto new_parkable_string = base::MakeRefCounted<ParkableStringImpl>( |
| std::move(string), ParkableStringImpl::ParkableState::kParkable); |
| table_.insert(raw_ptr, new_parkable_string.get()); |
| return new_parkable_string; |
| } |
| |
| void ParkableStringManager::Remove(StringImpl* string) { |
| DCHECK(string); |
| DCHECK(ShouldPark(*string)); |
| auto it = table_.find(string); |
| DCHECK(it != table_.end()); |
| table_.erase(it); |
| } |
| |
| void ParkableStringManager::ParkAllIfRendererBackgrounded() { |
| DCHECK(IsMainThread()); |
| if (!IsRendererBackgrounded()) |
| return; |
| |
| size_t total_size = 0, count = 0; |
| for (ParkableStringImpl* str : table_.Values()) { |
| str->Park(); |
| total_size += str->CharactersSizeInBytes(); |
| count += 1; |
| } |
| |
| size_t total_size_kb = total_size / 1000; |
| UMA_HISTOGRAM_COUNTS_100000("Memory.MovableStringsTotalSizeKb", |
| total_size_kb); |
| UMA_HISTOGRAM_COUNTS_1000("Memory.MovableStringsCount", table_.size()); |
| } |
| |
| ParkableStringManager::ParkableStringManager() |
| : backgrounded_(false), table_() {} |
| |
| } // namespace blink |