Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Member Functions | Static Public Attributes | Private Member Functions | Friends | List of all members
flutter::PersistentCache Class Reference

#include <persistent_cache.h>

Inheritance diagram for flutter::PersistentCache:
GrContextOptions::PersistentCache

Classes

struct  CacheObjectHeader
 
struct  SkSLCache
 

Public Member Functions

 ~PersistentCache () override
 
void AddWorkerTaskRunner (const fml::RefPtr< fml::TaskRunner > &task_runner)
 
void RemoveWorkerTaskRunner (const fml::RefPtr< fml::TaskRunner > &task_runner)
 
bool StoredNewShaders () const
 
void ResetStoredNewShaders ()
 
void DumpSkp (const SkData &data)
 
bool IsDumpingSkp () const
 
void SetIsDumpingSkp (bool value)
 
bool Purge ()
 
sk_sp< SkDataload (const SkData &key) override
 
std::vector< SkSLCacheLoadSkSLs () const
 Load all the SkSL shader caches in the right directory.
 
size_t PrecompileKnownSkSLs (GrDirectContext *context) const
 Precompile SkSLs packaged with the application and gathered during previous runs in the given context.
 
std::vector< std::unique_ptr< fml::Mapping > > GetSkpsFromAssetManager () const
 
- Public Member Functions inherited from GrContextOptions::PersistentCache
virtual void store (const SkData &key, const SkData &data, const SkString &)
 

Static Public Member Functions

static PersistentCacheGetCacheForProcess ()
 
static void ResetCacheForProcess ()
 
static void SetCacheDirectoryPath (std::string path)
 
static std::string SkKeyToFilePath (const SkData &key)
 
static std::unique_ptr< fml::MallocMappingBuildCacheObject (const SkData &key, const SkData &data)
 
static void SetAssetManager (std::shared_ptr< AssetManager > value)
 
static std::shared_ptr< AssetManagerasset_manager ()
 
static bool cache_sksl ()
 
static void SetCacheSkSL (bool value)
 
static void MarkStrategySet ()
 

Static Public Attributes

static bool gIsReadOnly = false
 
static constexpr char kSkSLSubdirName [] = "sksl"
 
static constexpr char kAssetFileName [] = "io.flutter.shaders.json"
 

Private Member Functions

void store (const SkData &key, const SkData &data) override
 

Friends

class testing::ShellTest
 

Additional Inherited Members

- Protected Member Functions inherited from GrContextOptions::PersistentCache
 PersistentCache ()=default
 
 PersistentCache (const PersistentCache &)=delete
 
PersistentCacheoperator= (const PersistentCache &)=delete
 

Detailed Description

A cache of SkData that gets stored to disk.

This is mainly used for Shaders but is also written to by Dart. It is thread-safe for reading and writing from multiple threads.

Definition at line 30 of file persistent_cache.h.

Constructor & Destructor Documentation

◆ ~PersistentCache()

flutter::PersistentCache::~PersistentCache ( )
overridevirtualdefault

Reimplemented from GrContextOptions::PersistentCache.

Member Function Documentation

◆ AddWorkerTaskRunner()

void flutter::PersistentCache::AddWorkerTaskRunner ( const fml::RefPtr< fml::TaskRunner > &  task_runner)

Definition at line 444 of file persistent_cache.cc.

445 {
446 std::scoped_lock lock(worker_task_runners_mutex_);
447 worker_task_runners_.insert(task_runner);
448}

◆ asset_manager()

static std::shared_ptr< AssetManager > flutter::PersistentCache::asset_manager ( )
inlinestatic

Definition at line 122 of file persistent_cache.h.

122 {
123 return asset_manager_;
124 }

◆ BuildCacheObject()

std::unique_ptr< fml::MallocMapping > flutter::PersistentCache::BuildCacheObject ( const SkData key,
const SkData data 
)
static

Definition at line 378 of file persistent_cache.cc.

380 {
381 size_t total_size = sizeof(CacheObjectHeader) + key.size() + data.size();
382 uint8_t* mapping_buf = reinterpret_cast<uint8_t*>(malloc(total_size));
383 if (!mapping_buf) {
384 return nullptr;
385 }
386 auto mapping = std::make_unique<fml::MallocMapping>(mapping_buf, total_size);
387
388 CacheObjectHeader header(key.size());
389 memcpy(mapping_buf, &header, sizeof(CacheObjectHeader));
390 mapping_buf += sizeof(CacheObjectHeader);
391 memcpy(mapping_buf, key.data(), key.size());
392 mapping_buf += key.size();
393 memcpy(mapping_buf, data.data(), data.size());
394
395 return mapping;
396}
static size_t total_size(SkSBlockAllocator< N > &pool)
void * malloc(size_t size)
Definition allocation.cc:19
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
static const char header[]
Definition skpbench.cpp:88

◆ cache_sksl()

static bool flutter::PersistentCache::cache_sksl ( )
inlinestatic

Definition at line 126 of file persistent_cache.h.

126{ return cache_sksl_; }

◆ DumpSkp()

void flutter::PersistentCache::DumpSkp ( const SkData data)

Definition at line 426 of file persistent_cache.cc.

426 {
427 if (is_read_only_ || !IsValid()) {
428 FML_LOG(ERROR) << "Could not dump SKP from read-only or invalid persistent "
429 "cache.";
430 return;
431 }
432
433 std::stringstream name_stream;
435 name_stream << "shader_dump_" << std::to_string(ticks) << ".skp";
436 std::string file_name = name_stream.str();
437 FML_LOG(INFO) << "Dumping " << file_name;
438 auto mapping = std::make_unique<fml::DataMapping>(
439 std::vector<uint8_t>{data.bytes(), data.bytes() + data.size()});
440 PersistentCacheStore(GetWorkerTaskRunner(), cache_directory_,
441 std::move(file_name), std::move(mapping));
442}
constexpr int64_t ToNanoseconds() const
Definition time_delta.h:61
TimeDelta ToEpochDelta() const
Definition time_point.h:52
static TimePoint Now()
Definition time_point.cc:49
#define FML_LOG(severity)
Definition logging.h:82
static void PersistentCacheStore(const fml::RefPtr< fml::TaskRunner > &worker, const std::shared_ptr< fml::UniqueFD > &cache_directory, std::string key, std::unique_ptr< fml::Mapping > value)
#define ERROR(message)

◆ GetCacheForProcess()

PersistentCache * flutter::PersistentCache::GetCacheForProcess ( )
static

Definition at line 63 of file persistent_cache.cc.

63 {
64 std::scoped_lock lock(instance_mutex_);
65 if (gPersistentCache == nullptr) {
66 gPersistentCache.reset(new PersistentCache(gIsReadOnly));
67 }
68 return gPersistentCache.get();
69}

◆ GetSkpsFromAssetManager()

std::vector< std::unique_ptr< fml::Mapping > > flutter::PersistentCache::GetSkpsFromAssetManager ( ) const

Definition at line 476 of file persistent_cache.cc.

476 {
477 if (!asset_manager_) {
479 << "PersistentCache::GetSkpsFromAssetManager: Asset manager not set!";
480 return std::vector<std::unique_ptr<fml::Mapping>>();
481 }
482 return asset_manager_->GetAsMappings(".*\\.skp$", "shaders");
483}

◆ IsDumpingSkp()

bool flutter::PersistentCache::IsDumpingSkp ( ) const
inline

Definition at line 83 of file persistent_cache.h.

83{ return is_dumping_skp_; }

◆ load()

sk_sp< SkData > flutter::PersistentCache::load ( const SkData key)
overridevirtual

Returns the data for the key if it exists in the cache, otherwise returns null.

Implements GrContextOptions::PersistentCache.

Definition at line 330 of file persistent_cache.cc.

330 {
331 TRACE_EVENT0("flutter", "PersistentCacheLoad");
332 if (!IsValid()) {
333 return nullptr;
334 }
335 auto file_name = SkKeyToFilePath(key);
336 if (file_name.empty()) {
337 return nullptr;
338 }
339 auto result =
340 PersistentCache::LoadFile(*cache_directory_, file_name, false).value;
341 if (result != nullptr) {
342 TRACE_EVENT0("flutter", "PersistentCacheLoadHit");
343 }
344 return result;
345}
static std::string SkKeyToFilePath(const SkData &key)
GAsyncResult * result
#define TRACE_EVENT0(category_group, name)

◆ LoadSkSLs()

std::vector< PersistentCache::SkSLCache > flutter::PersistentCache::LoadSkSLs ( ) const

Load all the SkSL shader caches in the right directory.

Definition at line 221 of file persistent_cache.cc.

221 {
222 TRACE_EVENT0("flutter", "PersistentCache::LoadSkSLs");
223 std::vector<PersistentCache::SkSLCache> result;
224 fml::FileVisitor visitor = [&result](const fml::UniqueFD& directory,
225 const std::string& filename) {
226 SkSLCache cache = LoadFile(directory, filename, true);
227 if (cache.key != nullptr && cache.value != nullptr) {
228 result.push_back(cache);
229 } else {
230 FML_LOG(ERROR) << "Failed to load: " << filename;
231 }
232 return true;
233 };
234
235 // Only visit sksl_cache_directory_ if this persistent cache is valid.
236 // However, we'd like to continue visit the asset dir even if this persistent
237 // cache is invalid.
238 if (IsValid()) {
239 // In case `rewinddir` doesn't work reliably, load SkSLs from a freshly
240 // opened directory (https://github.com/flutter/flutter/issues/65258).
241 fml::UniqueFD fresh_dir =
243 if (fresh_dir.is_valid()) {
244 fml::VisitFiles(fresh_dir, visitor);
245 }
246 }
247
248 std::unique_ptr<fml::Mapping> mapping = nullptr;
249 if (asset_manager_ != nullptr) {
250 mapping = asset_manager_->GetAsMapping(kAssetFileName);
251 }
252 if (mapping == nullptr) {
253 FML_LOG(INFO) << "No sksl asset found.";
254 } else {
255 FML_LOG(INFO) << "Found sksl asset. Loading SkSLs from it...";
256 rapidjson::Document json_doc;
257 rapidjson::ParseResult parse_result =
258 json_doc.Parse(reinterpret_cast<const char*>(mapping->GetMapping()),
259 mapping->GetSize());
260 if (parse_result.IsError()) {
261 FML_LOG(ERROR) << "Failed to parse json file: " << kAssetFileName;
262 } else {
263 for (auto& item : json_doc["data"].GetObject()) {
264 sk_sp<SkData> key = ParseBase32(item.name.GetString());
265 sk_sp<SkData> sksl = ParseBase64(item.value.GetString());
266 if (key != nullptr && sksl != nullptr) {
267 result.push_back({key, sksl});
268 } else {
269 FML_LOG(ERROR) << "Failed to load: " << item.name.GetString();
270 }
271 }
272 }
273 }
274
275 return result;
276}
static constexpr char kSkSLSubdirName[]
static constexpr char kAssetFileName[]
bool is_valid() const
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
Definition switches.h:191
sk_sp< SkData > ParseBase32(const std::string &input)
sk_sp< SkData > ParseBase64(const std::string &input)
bool VisitFiles(const fml::UniqueFD &directory, const FileVisitor &visitor)
fml::UniqueFD OpenDirectoryReadOnly(const fml::UniqueFD &base_directory, const char *path)
Definition file.cc:97
std::function< bool(const fml::UniqueFD &directory, const std::string &filename)> FileVisitor
Definition file.h:98

◆ MarkStrategySet()

static void flutter::PersistentCache::MarkStrategySet ( )
inlinestatic

Definition at line 130 of file persistent_cache.h.

130{ strategy_set_ = true; }

◆ PrecompileKnownSkSLs()

size_t flutter::PersistentCache::PrecompileKnownSkSLs ( GrDirectContext context) const

Precompile SkSLs packaged with the application and gathered during previous runs in the given context.

Warning
The context must be the rendering context. This context may be destroyed during application suspension and subsequently recreated. The SkSLs must be precompiled again in the new context.
Parameters
contextThe rendering context to precompile shaders in.
Returns
The number of SkSLs precompiled.

Definition at line 194 of file persistent_cache.cc.

194 {
195 // clang-tidy has trouble reasoning about some of the complicated array and
196 // pointer-arithmetic code in rapidjson.
197 // NOLINTNEXTLINE(clang-analyzer-cplusplus.PlacementNew)
198 auto known_sksls = LoadSkSLs();
199 // A trace must be present even if no precompilations have been completed.
200 FML_TRACE_EVENT("flutter", "PersistentCache::PrecompileKnownSkSLs", "count",
201 known_sksls.size());
202
203 if (context == nullptr) {
204 return 0;
205 }
206
207 size_t precompiled_count = 0;
208 for (const auto& sksl : known_sksls) {
209 TRACE_EVENT0("flutter", "PrecompilingSkSL");
210 if (context->precompileShader(*sksl.key, *sksl.value)) {
211 precompiled_count++;
212 }
213 }
214
215 FML_TRACE_COUNTER("flutter", "PersistentCache::PrecompiledSkSLs",
216 reinterpret_cast<int64_t>(this), // Trace Counter ID
217 "Successful", precompiled_count);
218 return precompiled_count;
219}
bool precompileShader(const SkData &key, const SkData &data)
std::vector< SkSLCache > LoadSkSLs() const
Load all the SkSL shader caches in the right directory.
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)
Definition trace_event.h:85
#define FML_TRACE_EVENT(category_group, name,...)

◆ Purge()

bool flutter::PersistentCache::Purge ( )

Definition at line 81 of file persistent_cache.cc.

81 {
82 // Make sure that this is called after the worker task runner setup so all the
83 // file system modifications would happen on that single thread to avoid
84 // racing.
85 FML_CHECK(GetWorkerTaskRunner());
86
87 std::promise<bool> removed;
88 GetWorkerTaskRunner()->PostTask([&removed,
89 cache_directory = cache_directory_]() {
90 if (cache_directory->is_valid()) {
91 // Only remove files but not directories.
92 FML_LOG(INFO) << "Purge persistent cache.";
93 fml::FileVisitor delete_file = [](const fml::UniqueFD& directory,
94 const std::string& filename) {
95 // Do not delete directories. Return true to continue with other files.
96 if (fml::IsDirectory(directory, filename.c_str())) {
97 return true;
98 }
99 return fml::UnlinkFile(directory, filename.c_str());
100 };
101 removed.set_value(VisitFilesRecursively(*cache_directory, delete_file));
102 } else {
103 removed.set_value(false);
104 }
105 });
106 return removed.get_future().get();
107}
virtual void PostTask(const fml::closure &task) override
#define FML_CHECK(condition)
Definition logging.h:85
bool VisitFilesRecursively(const fml::UniqueFD &directory, const FileVisitor &visitor)
Definition file.cc:71

◆ RemoveWorkerTaskRunner()

void flutter::PersistentCache::RemoveWorkerTaskRunner ( const fml::RefPtr< fml::TaskRunner > &  task_runner)

Definition at line 450 of file persistent_cache.cc.

451 {
452 std::scoped_lock lock(worker_task_runners_mutex_);
453 auto found = worker_task_runners_.find(task_runner);
454 if (found != worker_task_runners_.end()) {
455 worker_task_runners_.erase(found);
456 }
457}

◆ ResetCacheForProcess()

void flutter::PersistentCache::ResetCacheForProcess ( )
static

Definition at line 71 of file persistent_cache.cc.

71 {
72 std::scoped_lock lock(instance_mutex_);
73 gPersistentCache.reset(new PersistentCache(gIsReadOnly));
74 strategy_set_ = false;
75}

◆ ResetStoredNewShaders()

void flutter::PersistentCache::ResetStoredNewShaders ( )
inline

Definition at line 81 of file persistent_cache.h.

81{ stored_new_shaders_ = false; }

◆ SetAssetManager()

void flutter::PersistentCache::SetAssetManager ( std::shared_ptr< AssetManager value)
static

Set the asset manager from which PersistentCache can load SkLSs. A nullptr can be provided to clear the asset manager.

Definition at line 470 of file persistent_cache.cc.

470 {
471 TRACE_EVENT_INSTANT0("flutter", "PersistentCache::SetAssetManager");
472 asset_manager_ = std::move(value);
473}
#define TRACE_EVENT_INSTANT0(category_group, name)

◆ SetCacheDirectoryPath()

void flutter::PersistentCache::SetCacheDirectoryPath ( std::string  path)
static

Definition at line 77 of file persistent_cache.cc.

77 {
78 cache_base_path_ = std::move(path);
79}
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57

◆ SetCacheSkSL()

void flutter::PersistentCache::SetCacheSkSL ( bool  value)
static

Definition at line 54 of file persistent_cache.cc.

54 {
55 if (strategy_set_ && value != cache_sksl_) {
56 FML_LOG(ERROR) << "Cache SkSL can only be set before the "
57 "GrContextOptions::fShaderCacheStrategy is set.";
58 return;
59 }
60 cache_sksl_ = value;
61}
uint8_t value

◆ SetIsDumpingSkp()

void flutter::PersistentCache::SetIsDumpingSkp ( bool  value)
inline

Definition at line 84 of file persistent_cache.h.

84{ is_dumping_skp_ = value; }

◆ SkKeyToFilePath()

std::string flutter::PersistentCache::SkKeyToFilePath ( const SkData key)
static

Definition at line 36 of file persistent_cache.cc.

36 {
37 if (key.data() == nullptr || key.size() == 0) {
38 return "";
39 }
40
41 uint8_t sha_digest[SHA_DIGEST_LENGTH];
42 SHA1(static_cast<const uint8_t*>(key.data()), key.size(), sha_digest);
43
44 std::string_view view(reinterpret_cast<const char*>(sha_digest),
45 SHA_DIGEST_LENGTH);
46 return fml::HexEncode(view);
47}
std::string HexEncode(std::string_view input)
Definition hex_codec.cc:14

◆ store()

void flutter::PersistentCache::store ( const SkData key,
const SkData data 
)
overrideprivatevirtual

Reimplemented from GrContextOptions::PersistentCache.

Definition at line 399 of file persistent_cache.cc.

399 {
400 stored_new_shaders_ = true;
401
402 if (is_read_only_) {
403 return;
404 }
405
406 if (!IsValid()) {
407 return;
408 }
409
410 auto file_name = SkKeyToFilePath(key);
411
412 if (file_name.empty()) {
413 return;
414 }
415
416 std::unique_ptr<fml::MallocMapping> mapping = BuildCacheObject(key, data);
417 if (!mapping) {
418 return;
419 }
420
421 PersistentCacheStore(GetWorkerTaskRunner(),
422 cache_sksl_ ? sksl_cache_directory_ : cache_directory_,
423 std::move(file_name), std::move(mapping));
424}
static std::unique_ptr< fml::MallocMapping > BuildCacheObject(const SkData &key, const SkData &data)
Definition ref_ptr.h:256

◆ StoredNewShaders()

bool flutter::PersistentCache::StoredNewShaders ( ) const
inline

Definition at line 80 of file persistent_cache.h.

80{ return stored_new_shaders_; }

Friends And Related Symbol Documentation

◆ testing::ShellTest

friend class testing::ShellTest
friend

Definition at line 175 of file persistent_cache.h.

Member Data Documentation

◆ gIsReadOnly

bool flutter::PersistentCache::gIsReadOnly = false
static

Definition at line 37 of file persistent_cache.h.

◆ kAssetFileName

constexpr char flutter::PersistentCache::kAssetFileName[] = "io.flutter.shaders.json"
staticconstexpr

Definition at line 133 of file persistent_cache.h.

◆ kSkSLSubdirName

constexpr char flutter::PersistentCache::kSkSLSubdirName[] = "sksl"
staticconstexpr

Definition at line 132 of file persistent_cache.h.


The documentation for this class was generated from the following files: