Flutter Engine
flutter::PersistentCache Class Reference

#include <persistent_cache.h>

Inheritance diagram for flutter::PersistentCache:

Classes

struct  CacheObjectHeader
 
struct  SkSLCache
 

Public Member Functions

 ~PersistentCache () override
 
void AddWorkerTaskRunner (fml::RefPtr< fml::TaskRunner > task_runner)
 
void RemoveWorkerTaskRunner (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< SkData > load (const SkData &key) override
 
std::vector< SkSLCacheLoadSkSLs () const
 Load all the SkSL shader caches in the right directory. More...
 
size_t PrecompileKnownSkSLs (GrDirectContext *context) const
 Precompile SkSLs packaged with the application and gathered during previous runs in the given context. More...
 
std::vector< std::unique_ptr< fml::Mapping > > GetSkpsFromAssetManager () const
 

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"
 

Friends

class testing::ShellTest
 

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 28 of file persistent_cache.h.

Constructor & Destructor Documentation

◆ ~PersistentCache()

flutter::PersistentCache::~PersistentCache ( )
overridedefault

Referenced by LoadSkSLs().

Member Function Documentation

◆ AddWorkerTaskRunner()

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

Definition at line 437 of file persistent_cache.cc.

Referenced by flutter::Shell::IsSetup().

438  {
439  std::scoped_lock lock(worker_task_runners_mutex_);
440  worker_task_runners_.insert(task_runner);
441 }

◆ asset_manager()

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

Definition at line 120 of file persistent_cache.h.

Referenced by flutter_runner::Engine::Engine().

120  {
121  return asset_manager_;
122  }

◆ BuildCacheObject()

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

Definition at line 371 of file persistent_cache.cc.

References key, flutter::PersistentCacheStore(), and SkKeyToFilePath().

Referenced by flutter::testing::TEST_F().

373  {
374  size_t total_size = sizeof(CacheObjectHeader) + key.size() + data.size();
375  uint8_t* mapping_buf = reinterpret_cast<uint8_t*>(malloc(total_size));
376  if (!mapping_buf) {
377  return nullptr;
378  }
379  auto mapping = std::make_unique<fml::MallocMapping>(mapping_buf, total_size);
380 
381  CacheObjectHeader header(key.size());
382  memcpy(mapping_buf, &header, sizeof(CacheObjectHeader));
383  mapping_buf += sizeof(CacheObjectHeader);
384  memcpy(mapping_buf, key.data(), key.size());
385  mapping_buf += key.size();
386  memcpy(mapping_buf, data.data(), data.size());
387 
388  return mapping;
389 }

◆ cache_sksl()

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

Definition at line 124 of file persistent_cache.h.

References value.

Referenced by flutter::MakeDefaultContextOptions(), and Purge().

124 { return cache_sksl_; }

◆ DumpSkp()

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

Definition at line 419 of file persistent_cache.cc.

References FML_LOG, fml::TimePoint::Now(), flutter::PersistentCacheStore(), fml::TimePoint::ToEpochDelta(), and fml::TimeDelta::ToNanoseconds().

Referenced by flutter::Rasterizer::Draw().

419  {
420  if (is_read_only_ || !IsValid()) {
421  FML_LOG(ERROR) << "Could not dump SKP from read-only or invalid persistent "
422  "cache.";
423  return;
424  }
425 
426  std::stringstream name_stream;
428  name_stream << "shader_dump_" << std::to_string(ticks) << ".skp";
429  std::string file_name = name_stream.str();
430  FML_LOG(INFO) << "Dumping " << file_name;
431  auto mapping = std::make_unique<fml::DataMapping>(
432  std::vector<uint8_t>{data.bytes(), data.bytes() + data.size()});
433  PersistentCacheStore(GetWorkerTaskRunner(), cache_directory_,
434  std::move(file_name), std::move(mapping));
435 }
TimeDelta ToEpochDelta() const
Definition: time_point.h:47
#define FML_LOG(severity)
Definition: logging.h:65
static bool IsValid(double value)
static void PersistentCacheStore(fml::RefPtr< fml::TaskRunner > worker, std::shared_ptr< fml::UniqueFD > cache_directory, std::string key, std::unique_ptr< fml::Mapping > value)
constexpr int64_t ToNanoseconds() const
Definition: time_delta.h:61
static TimePoint Now()
Definition: time_point.cc:39

◆ GetCacheForProcess()

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

Definition at line 62 of file persistent_cache.cc.

References gIsReadOnly.

Referenced by flutter::testing::CheckTwoSkSLsAreLoaded(), flutter::Rasterizer::Draw(), flutter_runner::Engine::Engine(), flutter::Shell::IsSetup(), flutter::GPUSurfaceMetal::IsValid(), flutter::MakeDefaultContextOptions(), flutter::GPUSurfaceGL::MakeGLContext(), flutter::Shell::RegisterImageDecoder(), flutter::testing::ResetAssetManager(), flutter::testing::TEST_F(), and flutter::Shell::~Shell().

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

◆ GetSkpsFromAssetManager()

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

Definition at line 469 of file persistent_cache.cc.

References FML_LOG.

469  {
470  if (!asset_manager_) {
471  FML_LOG(ERROR)
472  << "PersistentCache::GetSkpsFromAssetManager: Asset manager not set!";
473  return std::vector<std::unique_ptr<fml::Mapping>>();
474  }
475  return asset_manager_->GetAsMappings(".*\\.skp$", "shaders");
476 }
#define FML_LOG(severity)
Definition: logging.h:65

◆ IsDumpingSkp()

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

Definition at line 81 of file persistent_cache.h.

Referenced by flutter::Rasterizer::Draw().

81 { return is_dumping_skp_; }

◆ load()

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

Definition at line 326 of file persistent_cache.cc.

References result, SkKeyToFilePath(), and TRACE_EVENT0.

326  {
327  TRACE_EVENT0("flutter", "PersistentCacheLoad");
328  if (!IsValid()) {
329  return nullptr;
330  }
331  auto file_name = SkKeyToFilePath(key);
332  if (file_name.size() == 0) {
333  return nullptr;
334  }
335  auto result =
336  PersistentCache::LoadFile(*cache_directory_, file_name, false).value;
337  if (result != nullptr) {
338  TRACE_EVENT0("flutter", "PersistentCacheLoadHit");
339  }
340  return result;
341 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
std::unique_ptr< fml::Mapping > LoadFile(int namespace_fd, const char *path, bool executable)
GAsyncResult * result
static bool IsValid(double value)
static std::string SkKeyToFilePath(const SkData &key)

◆ LoadSkSLs()

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

Load all the SkSL shader caches in the right directory.

Definition at line 217 of file persistent_cache.cc.

References FML_LOG, fml::UniqueObject< T, Traits >::is_valid(), kAssetFileName, key, flutter::PersistentCache::SkSLCache::key, flutter::PersistentCache::CacheObjectHeader::key_size, flutter::PersistentCache::CacheObjectHeader::kSignature, kSkSLSubdirName, flutter::PersistentCache::CacheObjectHeader::kVersion1, fml::OpenDirectoryReadOnly(), fml::OpenFileReadOnly(), flutter::ParseBase32(), flutter::ParseBase64(), result, flutter::PersistentCache::CacheObjectHeader::signature, TRACE_EVENT0, flutter::PersistentCache::SkSLCache::value, flutter::PersistentCache::CacheObjectHeader::version, fml::VisitFiles(), and ~PersistentCache().

Referenced by flutter::testing::CheckTwoSkSLsAreLoaded(), PrecompileKnownSkSLs(), flutter::Shell::RegisterImageDecoder(), and flutter::testing::TEST_F().

217  {
218  TRACE_EVENT0("flutter", "PersistentCache::LoadSkSLs");
219  std::vector<PersistentCache::SkSLCache> result;
220  fml::FileVisitor visitor = [&result](const fml::UniqueFD& directory,
221  const std::string& filename) {
222  SkSLCache cache = LoadFile(directory, filename, true);
223  if (cache.key != nullptr && cache.value != nullptr) {
224  result.push_back(cache);
225  } else {
226  FML_LOG(ERROR) << "Failed to load: " << filename;
227  }
228  return true;
229  };
230 
231  // Only visit sksl_cache_directory_ if this persistent cache is valid.
232  // However, we'd like to continue visit the asset dir even if this persistent
233  // cache is invalid.
234  if (IsValid()) {
235  // In case `rewinddir` doesn't work reliably, load SkSLs from a freshly
236  // opened directory (https://github.com/flutter/flutter/issues/65258).
237  fml::UniqueFD fresh_dir =
238  fml::OpenDirectoryReadOnly(*cache_directory_, kSkSLSubdirName);
239  if (fresh_dir.is_valid()) {
240  fml::VisitFiles(fresh_dir, visitor);
241  }
242  }
243 
244  std::unique_ptr<fml::Mapping> mapping = nullptr;
245  if (asset_manager_ != nullptr) {
246  mapping = asset_manager_->GetAsMapping(kAssetFileName);
247  }
248  if (mapping == nullptr) {
249  FML_LOG(INFO) << "No sksl asset found.";
250  } else {
251  FML_LOG(INFO) << "Found sksl asset. Loading SkSLs from it...";
252  rapidjson::Document json_doc;
253  rapidjson::ParseResult parse_result =
254  json_doc.Parse(reinterpret_cast<const char*>(mapping->GetMapping()),
255  mapping->GetSize());
256  if (parse_result.IsError()) {
257  FML_LOG(ERROR) << "Failed to parse json file: " << kAssetFileName;
258  } else {
259  for (auto& item : json_doc["data"].GetObject()) {
260  sk_sp<SkData> key = ParseBase32(item.name.GetString());
261  sk_sp<SkData> sksl = ParseBase64(item.value.GetString());
262  if (key != nullptr && sksl != nullptr) {
263  result.push_back({key, sksl});
264  } else {
265  FML_LOG(ERROR) << "Failed to load: " << item.name.GetString();
266  }
267  }
268  }
269  }
270 
271  return result;
272 }
sk_sp< SkData > ParseBase64(const std::string &input)
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
std::function< bool(const fml::UniqueFD &directory, const std::string &filename)> FileVisitor
Definition: file.h:98
std::unique_ptr< fml::Mapping > LoadFile(int namespace_fd, const char *path, bool executable)
GAsyncResult * result
sk_sp< SkData > ParseBase32(const std::string &input)
#define FML_LOG(severity)
Definition: logging.h:65
static constexpr char kAssetFileName[]
bool is_valid() const
Definition: unique_object.h:89
static bool IsValid(double value)
static constexpr char kSkSLSubdirName[]
bool VisitFiles(const fml::UniqueFD &directory, const FileVisitor &visitor)
Definition: file_posix.cc:235
fml::UniqueFD OpenDirectoryReadOnly(const fml::UniqueFD &base_directory, const char *path)
Definition: file.cc:97

◆ MarkStrategySet()

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

Definition at line 128 of file persistent_cache.h.

Referenced by flutter::MakeDefaultContextOptions().

128 { 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 193 of file persistent_cache.cc.

References FML_TRACE_COUNTER, FML_TRACE_EVENT, LoadSkSLs(), and TRACE_EVENT0.

Referenced by flutter::GPUSurfaceMetal::IsValid(), and flutter::GPUSurfaceGL::MakeGLContext().

193  {
194  auto known_sksls = LoadSkSLs();
195  // A trace must be present even if no precompilations have been completed.
196  FML_TRACE_EVENT("flutter", "PersistentCache::PrecompileKnownSkSLs", "count",
197  known_sksls.size());
198 
199  if (context == nullptr) {
200  return 0;
201  }
202 
203  size_t precompiled_count = 0;
204  for (const auto& sksl : known_sksls) {
205  TRACE_EVENT0("flutter", "PrecompilingSkSL");
206  if (context->precompileShader(*sksl.key, *sksl.value)) {
207  precompiled_count++;
208  }
209  }
210 
211  FML_TRACE_COUNTER("flutter", "PersistentCache::PrecompiledSkSLs",
212  reinterpret_cast<int64_t>(this), // Trace Counter ID
213  "Successful", precompiled_count);
214  return precompiled_count;
215 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)
Definition: trace_event.h:69
std::vector< SkSLCache > LoadSkSLs() const
Load all the SkSL shader caches in the right directory.
#define FML_TRACE_EVENT(category_group, name,...)
Definition: trace_event.h:86

◆ Purge()

bool flutter::PersistentCache::Purge ( )

Definition at line 80 of file persistent_cache.cc.

References cache_sksl(), CreateDirectory, FML_CHECK, FML_LOG, fml::paths::GetCachesDirectory(), flutter::GetFlutterEngineVersion(), flutter::GetSkiaVersion(), fml::UniqueObject< T, Traits >::is_valid(), fml::IsDirectory(), fml::kRead, fml::kReadWrite, kSkSLSubdirName, fml::OpenDirectory(), fml::OpenDirectoryReadOnly(), fml::TaskRunner::PostTask(), fml::RemoveDirectoryRecursively(), fml::UnlinkFile(), fml::VisitFiles(), and fml::VisitFilesRecursively().

Referenced by flutter::Shell::IsSetup().

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

◆ RemoveWorkerTaskRunner()

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

Definition at line 443 of file persistent_cache.cc.

Referenced by flutter::Shell::~Shell().

444  {
445  std::scoped_lock lock(worker_task_runners_mutex_);
446  auto found = worker_task_runners_.find(task_runner);
447  if (found != worker_task_runners_.end()) {
448  worker_task_runners_.erase(found);
449  }
450 }

◆ ResetCacheForProcess()

void flutter::PersistentCache::ResetCacheForProcess ( )
static

Definition at line 70 of file persistent_cache.cc.

References gIsReadOnly.

Referenced by flutter::testing::TEST_F().

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

◆ ResetStoredNewShaders()

void flutter::PersistentCache::ResetStoredNewShaders ( )
inline

Definition at line 79 of file persistent_cache.h.

Referenced by flutter::Rasterizer::Draw().

79 { 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 463 of file persistent_cache.cc.

References TRACE_EVENT_INSTANT0, and value.

Referenced by flutter::testing::ResetAssetManager(), and flutter::RunConfiguration::RunConfiguration().

463  {
464  TRACE_EVENT_INSTANT0("flutter", "PersistentCache::SetAssetManager");
465  asset_manager_ = value;
466 }
#define TRACE_EVENT_INSTANT0(category_group, name)
Definition: trace_event.h:119
uint8_t value

◆ SetCacheDirectoryPath()

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

Definition at line 76 of file persistent_cache.cc.

References flutter::path.

Referenced by FlutterEngineInitialize(), and flutter::testing::TEST_F().

76  {
77  cache_base_path_ = path;
78 }
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32

◆ SetCacheSkSL()

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

Definition at line 53 of file persistent_cache.cc.

References FML_LOG, and value.

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

◆ SetIsDumpingSkp()

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

Definition at line 82 of file persistent_cache.h.

References key, and value.

Referenced by flutter::Shell::IsSetup().

82 { is_dumping_skp_ = value; }
uint8_t value

◆ SkKeyToFilePath()

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

Definition at line 35 of file persistent_cache.cc.

References gIsReadOnly, fml::HexEncode(), and view.

Referenced by BuildCacheObject(), load(), and flutter::testing::TEST_F().

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

◆ StoredNewShaders()

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

Definition at line 78 of file persistent_cache.h.

Referenced by flutter::Rasterizer::Draw().

78 { return stored_new_shaders_; }

Friends And Related Function Documentation

◆ testing::ShellTest

friend class testing::ShellTest
friend

Definition at line 173 of file persistent_cache.h.

Member Data Documentation

◆ gIsReadOnly

bool flutter::PersistentCache::gIsReadOnly = false
static

◆ kAssetFileName

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

Definition at line 131 of file persistent_cache.h.

Referenced by LoadSkSLs(), and flutter::testing::TEST_F().

◆ kSkSLSubdirName

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

Definition at line 130 of file persistent_cache.h.

Referenced by LoadSkSLs(), Purge(), and flutter::testing::TEST_F().


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