未验证 提交 cc44ca5d 编写于 作者: C Chinmay Garde 提交者: GitHub

Perform persistent cache stores on the IO thread outside the frame workload. (#6350)

上级 f2a3df97
......@@ -9,6 +9,7 @@
#include "flutter/fml/base32.h"
#include "flutter/fml/file.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
......@@ -40,15 +41,16 @@ PersistentCache* PersistentCache::GetCacheForProcess() {
}
PersistentCache::PersistentCache()
: cache_directory_(CreateDirectory(fml::paths::GetCachesDirectory(),
{
"flutter_engine", //
GetFlutterEngineVersion(), //
"skia", //
GetSkiaVersion() //
},
fml::FilePermission::kReadWrite)) {
if (!cache_directory_.is_valid()) {
: cache_directory_(std::make_shared<fml::UniqueFD>(
CreateDirectory(fml::paths::GetCachesDirectory(),
{
"flutter_engine", //
GetFlutterEngineVersion(), //
"skia", //
GetSkiaVersion() //
},
fml::FilePermission::kReadWrite))) {
if (!IsValid()) {
FML_LOG(ERROR) << "Could not acquire the persistent cache directory. "
"Caching of GPU resources on disk is disabled.";
}
......@@ -56,17 +58,21 @@ PersistentCache::PersistentCache()
PersistentCache::~PersistentCache() = default;
bool PersistentCache::IsValid() const {
return cache_directory_ && cache_directory_->is_valid();
}
// |GrContextOptions::PersistentCache|
sk_sp<SkData> PersistentCache::load(const SkData& key) {
TRACE_EVENT0("flutter", "PersistentCacheLoad");
if (!cache_directory_.is_valid()) {
if (!IsValid()) {
return nullptr;
}
auto file_name = SkKeyToFilePath(key);
if (file_name.size() == 0) {
return nullptr;
}
auto file = fml::OpenFile(cache_directory_, file_name.c_str(), false,
auto file = fml::OpenFile(*cache_directory_, file_name.c_str(), false,
fml::FilePermission::kRead);
if (!file.is_valid()) {
return nullptr;
......@@ -80,23 +86,81 @@ sk_sp<SkData> PersistentCache::load(const SkData& key) {
return SkData::MakeWithCopy(mapping->GetMapping(), mapping->GetSize());
}
static void PersistentCacheStore(fml::RefPtr<fml::TaskRunner> worker,
std::shared_ptr<fml::UniqueFD> cache_directory,
std::string key,
std::unique_ptr<fml::Mapping> value) {
auto task = fml::MakeCopyable([cache_directory, //
file_name = std::move(key), //
mapping = std::move(value) //
]() mutable {
TRACE_EVENT0("flutter", "PersistentCacheStore");
if (!fml::WriteAtomically(*cache_directory, //
file_name.c_str(), //
*mapping) //
) {
FML_DLOG(ERROR) << "Could not write cache contents to persistent store.";
}
});
if (!worker) {
FML_LOG(ERROR)
<< "The persistent cache has no available workers. Performing the task "
"on the current thread. This slow operation is going to occur on a "
"frame workload.";
task();
} else {
worker->PostTask(std::move(task));
}
}
// |GrContextOptions::PersistentCache|
void PersistentCache::store(const SkData& key, const SkData& data) {
TRACE_EVENT0("flutter", "PersistentCacheStore");
if (!cache_directory_.is_valid()) {
if (!IsValid()) {
return;
}
auto file_name = SkKeyToFilePath(key);
auto mapping =
std::make_unique<fml::NonOwnedMapping>(data.bytes(), data.size());
if (!fml::WriteAtomically(cache_directory_, //
file_name.c_str(), //
*mapping) //
) {
FML_DLOG(ERROR) << "Could not write cache contents to persistent store.";
if (file_name.size() == 0) {
return;
}
auto mapping = std::make_unique<fml::DataMapping>(
std::vector<uint8_t>{data.bytes(), data.bytes() + data.size()});
if (mapping == nullptr || mapping->GetSize() == 0) {
return;
}
PersistentCacheStore(GetWorkerTaskRunner(), cache_directory_,
std::move(file_name), std::move(mapping));
}
void PersistentCache::AddWorkerTaskRunner(
fml::RefPtr<fml::TaskRunner> task_runner) {
std::lock_guard<std::mutex> lock(worker_task_runners_mutex_);
worker_task_runners_.insert(task_runner);
}
void PersistentCache::RemoveWorkerTaskRunner(
fml::RefPtr<fml::TaskRunner> task_runner) {
std::lock_guard<std::mutex> lock(worker_task_runners_mutex_);
auto found = worker_task_runners_.find(task_runner);
if (found != worker_task_runners_.end()) {
worker_task_runners_.erase(found);
}
}
fml::RefPtr<fml::TaskRunner> PersistentCache::GetWorkerTaskRunner() const {
fml::RefPtr<fml::TaskRunner> worker;
std::lock_guard<std::mutex> lock(worker_task_runners_mutex_);
if (!worker_task_runners_.empty()) {
worker = *worker_task_runners_.begin();
}
return worker;
}
} // namespace shell
......@@ -5,9 +5,13 @@
#ifndef FLUTTER_SHELL_COMMON_PERSISTENT_CACHE_H_
#define FLUTTER_SHELL_COMMON_PERSISTENT_CACHE_H_
#include <memory>
#include <mutex>
#include <set>
#include "flutter/fml/macros.h"
#include "flutter/fml/synchronization/thread_annotations.h"
#include "flutter/fml/task_runner.h"
#include "flutter/fml/unique_fd.h"
#include "third_party/skia/include/gpu/GrContextOptions.h"
......@@ -19,8 +23,17 @@ class PersistentCache : public GrContextOptions::PersistentCache {
~PersistentCache() override;
void AddWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);
void RemoveWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);
private:
fml::UniqueFD cache_directory_;
std::shared_ptr<fml::UniqueFD> cache_directory_;
mutable std::mutex worker_task_runners_mutex_;
std::multiset<fml::RefPtr<fml::TaskRunner>> worker_task_runners_
FML_GUARDED_BY(worker_task_runners_mutex_);
bool IsValid() const;
PersistentCache();
......@@ -30,6 +43,8 @@ class PersistentCache : public GrContextOptions::PersistentCache {
// |GrContextOptions::PersistentCache|
void store(const SkData& key, const SkData& data) override;
fml::RefPtr<fml::TaskRunner> GetWorkerTaskRunner() const;
FML_DISALLOW_COPY_AND_ASSIGN(PersistentCache);
};
......
......@@ -23,6 +23,7 @@
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/start_up.h"
#include "flutter/shell/common/engine.h"
#include "flutter/shell/common/persistent_cache.h"
#include "flutter/shell/common/skia_event_tracer_impl.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/vsync_waiter.h"
......@@ -293,6 +294,9 @@ Shell::Shell(blink::TaskRunners task_runners, blink::Settings settings)
}
Shell::~Shell() {
PersistentCache::GetCacheForProcess()->RemoveWorkerTaskRunner(
task_runners_.GetIOTaskRunner());
if (auto vm = blink::DartVM::ForProcessIfInitialized()) {
vm->GetServiceProtocol().RemoveHandler(this);
}
......@@ -370,6 +374,9 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
vm->GetServiceProtocol().AddHandler(this);
}
PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
task_runners_.GetIOTaskRunner());
return true;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册