Skip to content

Commit cc44ca5

Browse files
authored
Perform persistent cache stores on the IO thread outside the frame workload. (flutter#6350)
1 parent f2a3df9 commit cc44ca5

File tree

3 files changed

+108
-22
lines changed

3 files changed

+108
-22
lines changed

shell/common/persistent_cache.cc

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "flutter/fml/base32.h"
1111
#include "flutter/fml/file.h"
12+
#include "flutter/fml/make_copyable.h"
1213
#include "flutter/fml/mapping.h"
1314
#include "flutter/fml/paths.h"
1415
#include "flutter/fml/trace_event.h"
@@ -40,33 +41,38 @@ PersistentCache* PersistentCache::GetCacheForProcess() {
4041
}
4142

4243
PersistentCache::PersistentCache()
43-
: cache_directory_(CreateDirectory(fml::paths::GetCachesDirectory(),
44-
{
45-
"flutter_engine", //
46-
GetFlutterEngineVersion(), //
47-
"skia", //
48-
GetSkiaVersion() //
49-
},
50-
fml::FilePermission::kReadWrite)) {
51-
if (!cache_directory_.is_valid()) {
44+
: cache_directory_(std::make_shared<fml::UniqueFD>(
45+
CreateDirectory(fml::paths::GetCachesDirectory(),
46+
{
47+
"flutter_engine", //
48+
GetFlutterEngineVersion(), //
49+
"skia", //
50+
GetSkiaVersion() //
51+
},
52+
fml::FilePermission::kReadWrite))) {
53+
if (!IsValid()) {
5254
FML_LOG(ERROR) << "Could not acquire the persistent cache directory. "
5355
"Caching of GPU resources on disk is disabled.";
5456
}
5557
}
5658

5759
PersistentCache::~PersistentCache() = default;
5860

61+
bool PersistentCache::IsValid() const {
62+
return cache_directory_ && cache_directory_->is_valid();
63+
}
64+
5965
// |GrContextOptions::PersistentCache|
6066
sk_sp<SkData> PersistentCache::load(const SkData& key) {
6167
TRACE_EVENT0("flutter", "PersistentCacheLoad");
62-
if (!cache_directory_.is_valid()) {
68+
if (!IsValid()) {
6369
return nullptr;
6470
}
6571
auto file_name = SkKeyToFilePath(key);
6672
if (file_name.size() == 0) {
6773
return nullptr;
6874
}
69-
auto file = fml::OpenFile(cache_directory_, file_name.c_str(), false,
75+
auto file = fml::OpenFile(*cache_directory_, file_name.c_str(), false,
7076
fml::FilePermission::kRead);
7177
if (!file.is_valid()) {
7278
return nullptr;
@@ -80,23 +86,81 @@ sk_sp<SkData> PersistentCache::load(const SkData& key) {
8086
return SkData::MakeWithCopy(mapping->GetMapping(), mapping->GetSize());
8187
}
8288

89+
static void PersistentCacheStore(fml::RefPtr<fml::TaskRunner> worker,
90+
std::shared_ptr<fml::UniqueFD> cache_directory,
91+
std::string key,
92+
std::unique_ptr<fml::Mapping> value) {
93+
auto task = fml::MakeCopyable([cache_directory, //
94+
file_name = std::move(key), //
95+
mapping = std::move(value) //
96+
]() mutable {
97+
TRACE_EVENT0("flutter", "PersistentCacheStore");
98+
if (!fml::WriteAtomically(*cache_directory, //
99+
file_name.c_str(), //
100+
*mapping) //
101+
) {
102+
FML_DLOG(ERROR) << "Could not write cache contents to persistent store.";
103+
}
104+
});
105+
106+
if (!worker) {
107+
FML_LOG(ERROR)
108+
<< "The persistent cache has no available workers. Performing the task "
109+
"on the current thread. This slow operation is going to occur on a "
110+
"frame workload.";
111+
task();
112+
} else {
113+
worker->PostTask(std::move(task));
114+
}
115+
}
116+
83117
// |GrContextOptions::PersistentCache|
84118
void PersistentCache::store(const SkData& key, const SkData& data) {
85-
TRACE_EVENT0("flutter", "PersistentCacheStore");
86-
if (!cache_directory_.is_valid()) {
119+
if (!IsValid()) {
87120
return;
88121
}
89122

90123
auto file_name = SkKeyToFilePath(key);
91-
auto mapping =
92-
std::make_unique<fml::NonOwnedMapping>(data.bytes(), data.size());
93-
94-
if (!fml::WriteAtomically(cache_directory_, //
95-
file_name.c_str(), //
96-
*mapping) //
97-
) {
98-
FML_DLOG(ERROR) << "Could not write cache contents to persistent store.";
124+
125+
if (file_name.size() == 0) {
126+
return;
127+
}
128+
129+
auto mapping = std::make_unique<fml::DataMapping>(
130+
std::vector<uint8_t>{data.bytes(), data.bytes() + data.size()});
131+
132+
if (mapping == nullptr || mapping->GetSize() == 0) {
133+
return;
99134
}
135+
136+
PersistentCacheStore(GetWorkerTaskRunner(), cache_directory_,
137+
std::move(file_name), std::move(mapping));
138+
}
139+
140+
void PersistentCache::AddWorkerTaskRunner(
141+
fml::RefPtr<fml::TaskRunner> task_runner) {
142+
std::lock_guard<std::mutex> lock(worker_task_runners_mutex_);
143+
worker_task_runners_.insert(task_runner);
144+
}
145+
146+
void PersistentCache::RemoveWorkerTaskRunner(
147+
fml::RefPtr<fml::TaskRunner> task_runner) {
148+
std::lock_guard<std::mutex> lock(worker_task_runners_mutex_);
149+
auto found = worker_task_runners_.find(task_runner);
150+
if (found != worker_task_runners_.end()) {
151+
worker_task_runners_.erase(found);
152+
}
153+
}
154+
155+
fml::RefPtr<fml::TaskRunner> PersistentCache::GetWorkerTaskRunner() const {
156+
fml::RefPtr<fml::TaskRunner> worker;
157+
158+
std::lock_guard<std::mutex> lock(worker_task_runners_mutex_);
159+
if (!worker_task_runners_.empty()) {
160+
worker = *worker_task_runners_.begin();
161+
}
162+
163+
return worker;
100164
}
101165

102166
} // namespace shell

shell/common/persistent_cache.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
#ifndef FLUTTER_SHELL_COMMON_PERSISTENT_CACHE_H_
66
#define FLUTTER_SHELL_COMMON_PERSISTENT_CACHE_H_
77

8+
#include <memory>
89
#include <mutex>
10+
#include <set>
911

1012
#include "flutter/fml/macros.h"
13+
#include "flutter/fml/synchronization/thread_annotations.h"
14+
#include "flutter/fml/task_runner.h"
1115
#include "flutter/fml/unique_fd.h"
1216
#include "third_party/skia/include/gpu/GrContextOptions.h"
1317

@@ -19,8 +23,17 @@ class PersistentCache : public GrContextOptions::PersistentCache {
1923

2024
~PersistentCache() override;
2125

26+
void AddWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);
27+
28+
void RemoveWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);
29+
2230
private:
23-
fml::UniqueFD cache_directory_;
31+
std::shared_ptr<fml::UniqueFD> cache_directory_;
32+
mutable std::mutex worker_task_runners_mutex_;
33+
std::multiset<fml::RefPtr<fml::TaskRunner>> worker_task_runners_
34+
FML_GUARDED_BY(worker_task_runners_mutex_);
35+
36+
bool IsValid() const;
2437

2538
PersistentCache();
2639

@@ -30,6 +43,8 @@ class PersistentCache : public GrContextOptions::PersistentCache {
3043
// |GrContextOptions::PersistentCache|
3144
void store(const SkData& key, const SkData& data) override;
3245

46+
fml::RefPtr<fml::TaskRunner> GetWorkerTaskRunner() const;
47+
3348
FML_DISALLOW_COPY_AND_ASSIGN(PersistentCache);
3449
};
3550

shell/common/shell.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "flutter/runtime/dart_vm.h"
2424
#include "flutter/runtime/start_up.h"
2525
#include "flutter/shell/common/engine.h"
26+
#include "flutter/shell/common/persistent_cache.h"
2627
#include "flutter/shell/common/skia_event_tracer_impl.h"
2728
#include "flutter/shell/common/switches.h"
2829
#include "flutter/shell/common/vsync_waiter.h"
@@ -293,6 +294,9 @@ Shell::Shell(blink::TaskRunners task_runners, blink::Settings settings)
293294
}
294295

295296
Shell::~Shell() {
297+
PersistentCache::GetCacheForProcess()->RemoveWorkerTaskRunner(
298+
task_runners_.GetIOTaskRunner());
299+
296300
if (auto vm = blink::DartVM::ForProcessIfInitialized()) {
297301
vm->GetServiceProtocol().RemoveHandler(this);
298302
}
@@ -370,6 +374,9 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
370374
vm->GetServiceProtocol().AddHandler(this);
371375
}
372376

377+
PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
378+
task_runners_.GetIOTaskRunner());
379+
373380
return true;
374381
}
375382

0 commit comments

Comments
 (0)