blob: 3a1b3aa3e2d7017f7bc9946d90e4a806f1e9681d [file] [log] [blame]
// Copyright 2020 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_MANAGER_H_
#include "base/trace_event/memory_dump_provider.h"
#include "third_party/blink/renderer/platform/disk_data_allocator.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
class ParkableImage;
PLATFORM_EXPORT extern const base::Feature kParkableImagesToDisk;
// Manages parkable images, which are used in blink::BitmapImage. Currently,
// only records metrics for this. In the future we will park eligible images
// to disk.
// Main Thread only.
class PLATFORM_EXPORT ParkableImageManager
: public base::trace_event::MemoryDumpProvider {
public:
static ParkableImageManager& Instance();
~ParkableImageManager() override = default;
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs&,
base::trace_event::ProcessMemoryDump*) override;
// Number of parked and unparked images.
size_t Size() const LOCKS_EXCLUDED(lock_);
static bool IsParkableImagesToDiskEnabled() {
return base::FeatureList::IsEnabled(kParkableImagesToDisk);
}
private:
struct Statistics;
friend class ParkableImage;
friend class base::NoDestructor<ParkableImageManager>;
friend class ParkableImageBaseTest;
ParkableImageManager() = default;
DiskDataAllocator& data_allocator() const;
// Register and unregister a ParkableImage with the manager. ParkableImage
// should call these when created/destructed.
void Add(ParkableImage* image) LOCKS_EXCLUDED(lock_);
void Remove(ParkableImage* image) LOCKS_EXCLUDED(lock_);
void ScheduleDelayedParkingTaskIfNeeded() EXCLUSIVE_LOCKS_REQUIRED(lock_);
void MaybeParkImages() LOCKS_EXCLUDED(lock_);
Statistics ComputeStatistics() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
void RecordStatisticsAfter5Minutes() const LOCKS_EXCLUDED(lock_);
void MoveImage(ParkableImage* image,
WTF::HashSet<ParkableImage*>* from,
WTF::HashSet<ParkableImage*>* to)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void RecordDiskWriteTime(base::TimeDelta write_time) LOCKS_EXCLUDED(lock_) {
MutexLocker lock(lock_);
total_disk_write_time_ += write_time;
}
void RecordDiskReadTime(base::TimeDelta read_time) LOCKS_EXCLUDED(lock_) {
MutexLocker lock(lock_);
total_disk_read_time_ += read_time;
}
// Keeps track of whether the image is unparked or on disk. ParkableImage
// should call these when written to or read from disk.
void OnWrittenToDisk(ParkableImage* image) LOCKS_EXCLUDED(lock_);
void OnReadFromDisk(ParkableImage* image) LOCKS_EXCLUDED(lock_);
void SetDataAllocatorForTesting(
std::unique_ptr<DiskDataAllocator> allocator) {
allocator_for_testing_ = std::move(allocator);
}
void ResetForTesting();
constexpr static auto kDelayedParkingInterval =
base::TimeDelta::FromSeconds(2);
constexpr static const char* kAllocatorDumpName = "parkable_images";
mutable Mutex lock_;
// The following two sets are used to keep track of all ParkableImages that
// have been created. ParkableImages are added to |unparked_images_| upon
// creation, and removed from whichever set they are in at the time of their
// destruction.
//
// Parking or Unparking a ParkableImage moves the image to the appropriate
// set, using |OnReadFromDisk| and |OnWrittenToDisk|.
//
// |unparked_images_| keeps track of all images that have a in-memory
// representation.
//
// |on_disk_images_| keeps track of all images that do not have an in-memory
// representation. Accessing the data for any image in |on_disk_images_|
// involves a read from disk.
WTF::HashSet<ParkableImage*> unparked_images_ GUARDED_BY(lock_);
WTF::HashSet<ParkableImage*> on_disk_images_ GUARDED_BY(lock_);
bool has_pending_parking_task_ GUARDED_BY(lock_) = false;
bool has_posted_accounting_task_ = false;
base::TimeDelta total_disk_read_time_ GUARDED_BY(lock_) = base::TimeDelta();
base::TimeDelta total_disk_write_time_ GUARDED_BY(lock_) = base::TimeDelta();
std::unique_ptr<DiskDataAllocator> allocator_for_testing_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_MANAGER_H_