Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b40bc13

Browse files
committed
[fuchsia][shader warmup] Avoid recursively iterating over assets directory when loading skp's due to high cost of openat() on pkgfs
1 parent 069f28c commit b40bc13

File tree

9 files changed

+129
-18
lines changed

9 files changed

+129
-18
lines changed

assets/asset_manager.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,16 @@ std::unique_ptr<fml::Mapping> AssetManager::GetAsMapping(
7777

7878
// |AssetResolver|
7979
std::vector<std::unique_ptr<fml::Mapping>> AssetManager::GetAsMappings(
80-
const std::string& asset_pattern) const {
80+
const std::string& asset_pattern,
81+
const std::optional<std::string>& subdir) const {
8182
std::vector<std::unique_ptr<fml::Mapping>> mappings;
8283
if (asset_pattern.size() == 0) {
8384
return mappings;
8485
}
8586
TRACE_EVENT1("flutter", "AssetManager::GetAsMappings", "pattern",
8687
asset_pattern.c_str());
8788
for (const auto& resolver : resolvers_) {
88-
auto resolver_mappings = resolver->GetAsMappings(asset_pattern);
89+
auto resolver_mappings = resolver->GetAsMappings(asset_pattern, subdir);
8990
mappings.insert(mappings.end(),
9091
std::make_move_iterator(resolver_mappings.begin()),
9192
std::make_move_iterator(resolver_mappings.end()));

assets/asset_manager.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <memory>
1010
#include <string>
1111

12+
#include <optional>
1213
#include "flutter/assets/asset_resolver.h"
1314
#include "flutter/fml/macros.h"
1415
#include "flutter/fml/memory/ref_counted.h"
@@ -70,7 +71,8 @@ class AssetManager final : public AssetResolver {
7071

7172
// |AssetResolver|
7273
std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
73-
const std::string& asset_pattern) const override;
74+
const std::string& asset_pattern,
75+
const std::optional<std::string>& subdir) const override;
7476

7577
private:
7678
std::deque<std::unique_ptr<AssetResolver>> resolvers_;

assets/asset_resolver.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <string>
99
#include <vector>
1010

11+
#include <optional>
1112
#include "flutter/fml/macros.h"
1213
#include "flutter/fml/mapping.h"
1314

@@ -59,10 +60,24 @@ class AssetResolver {
5960
[[nodiscard]] virtual std::unique_ptr<fml::Mapping> GetAsMapping(
6061
const std::string& asset_name) const = 0;
6162

62-
// Same as GetAsMapping() but returns mappings for all files who's name
63-
// matches |pattern|. Returns empty vector if no matching assets are found
63+
//--------------------------------------------------------------------------
64+
/// @brief Same as GetAsMapping() but returns mappings for all files
65+
/// who's name matches a given pattern. Returns empty vector
66+
/// if no matching assets are found.
67+
///
68+
/// @param[in] asset_pattern The pattern to match file names against.
69+
///
70+
/// @param[in] subdir Optional subdirectory in which to search for files.
71+
/// If supplied this function does a flat search within the
72+
/// subdirectory instead of a recursive search through the entire
73+
/// assets directory.
74+
///
75+
/// @return Returns a vector of mappings of files which match the search
76+
/// parameters.
77+
///
6478
[[nodiscard]] virtual std::vector<std::unique_ptr<fml::Mapping>>
65-
GetAsMappings(const std::string& asset_pattern) const {
79+
GetAsMappings(const std::string& asset_pattern,
80+
const std::optional<std::string>& subdir) const {
6681
return {};
6782
};
6883

assets/directory_asset_bundle.cc

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "flutter/fml/eintr_wrapper.h"
1111
#include "flutter/fml/file.h"
1212
#include "flutter/fml/mapping.h"
13+
#include "flutter/fml/trace_event.h"
1314

1415
namespace flutter {
1516

@@ -60,7 +61,8 @@ std::unique_ptr<fml::Mapping> DirectoryAssetBundle::GetAsMapping(
6061
}
6162

6263
std::vector<std::unique_ptr<fml::Mapping>> DirectoryAssetBundle::GetAsMappings(
63-
const std::string& asset_pattern) const {
64+
const std::string& asset_pattern,
65+
const std::optional<std::string>& subdir) const {
6466
std::vector<std::unique_ptr<fml::Mapping>> mappings;
6567
if (!is_valid_) {
6668
FML_DLOG(WARNING) << "Asset bundle was not valid.";
@@ -70,9 +72,19 @@ std::vector<std::unique_ptr<fml::Mapping>> DirectoryAssetBundle::GetAsMappings(
7072
std::regex asset_regex(asset_pattern);
7173
fml::FileVisitor visitor = [&](const fml::UniqueFD& directory,
7274
const std::string& filename) {
75+
TRACE_EVENT0("flutter", "DirectoryAssetBundle::GetAsMappings FileVisitor");
76+
7377
if (std::regex_match(filename, asset_regex)) {
74-
auto mapping = std::make_unique<fml::FileMapping>(fml::OpenFile(
75-
directory, filename.c_str(), false, fml::FilePermission::kRead));
78+
TRACE_EVENT0("flutter", "Matched File");
79+
80+
fml::UniqueFD fd = fml::OpenFile(directory, filename.c_str(), false,
81+
fml::FilePermission::kRead);
82+
83+
if (fml::IsDirectory(fd)) {
84+
return true;
85+
}
86+
87+
auto mapping = std::make_unique<fml::FileMapping>(fd);
7688

7789
if (mapping && mapping->IsValid()) {
7890
mappings.push_back(std::move(mapping));
@@ -82,7 +94,18 @@ std::vector<std::unique_ptr<fml::Mapping>> DirectoryAssetBundle::GetAsMappings(
8294
}
8395
return true;
8496
};
85-
fml::VisitFilesRecursively(descriptor_, visitor);
97+
if (!subdir) {
98+
fml::VisitFilesRecursively(descriptor_, visitor);
99+
} else {
100+
fml::UniqueFD subdir_fd =
101+
fml::OpenFileReadOnly(descriptor_, subdir.value().c_str());
102+
if (!fml::IsDirectory(subdir_fd)) {
103+
FML_LOG(ERROR) << "Subdirectory path " << subdir.value()
104+
<< " is not a directory";
105+
return mappings;
106+
}
107+
fml::VisitFiles(subdir_fd, visitor);
108+
}
86109

87110
return mappings;
88111
}

assets/directory_asset_bundle.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_
66
#define FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_
77

8+
#include <optional>
89
#include "flutter/assets/asset_resolver.h"
910
#include "flutter/fml/macros.h"
1011
#include "flutter/fml/memory/ref_counted.h"
@@ -39,7 +40,8 @@ class DirectoryAssetBundle : public AssetResolver {
3940

4041
// |AssetResolver|
4142
std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
42-
const std::string& asset_pattern) const override;
43+
const std::string& asset_pattern,
44+
const std::optional<std::string>& subdir) const override;
4345

4446
FML_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle);
4547
};

common/graphics/persistent_cache.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ PersistentCache::GetSkpsFromAssetManager() const {
410410
<< "PersistentCache::GetSkpsFromAssetManager: Asset manager not set!";
411411
return std::vector<std::unique_ptr<fml::Mapping>>();
412412
}
413-
return asset_manager_->GetAsMappings(".*\\.skp$");
413+
return asset_manager_->GetAsMappings(".*\\.skp$", "shaders");
414414
}
415415

416416
} // namespace flutter

fml/platform/posix/file_posix.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "flutter/fml/eintr_wrapper.h"
1717
#include "flutter/fml/logging.h"
1818
#include "flutter/fml/mapping.h"
19+
#include "flutter/fml/trace_event.h"
1920
#include "flutter/fml/unique_fd.h"
2021

2122
namespace fml {
@@ -72,6 +73,7 @@ fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
7273
const char* path,
7374
bool create_if_necessary,
7475
FilePermission permission) {
76+
TRACE_EVENT0("flutter", "fml::OpenFile");
7577
if (path == nullptr) {
7678
return {};
7779
}

shell/common/shell_unittests.cc

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ class TestAssetResolver : public AssetResolver {
139139
}
140140

141141
std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
142-
const std::string& asset_pattern) const override {
142+
const std::string& asset_pattern,
143+
const std::optional<std::string>& subdir) const override {
143144
return {};
144145
};
145146

@@ -2436,16 +2437,78 @@ TEST_F(ShellTest, AssetManagerMulti) {
24362437
asset_manager.PushBack(
24372438
std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));
24382439

2439-
auto mappings = asset_manager.GetAsMappings("(.*)");
2440-
ASSERT_TRUE(mappings.size() == 4);
2440+
auto mappings = asset_manager.GetAsMappings("(.*)", std::nullopt);
2441+
EXPECT_EQ(mappings.size(), 4u);
24412442

24422443
std::vector<std::string> expected_results = {
24432444
"good0",
24442445
"good1",
24452446
};
24462447

2447-
mappings = asset_manager.GetAsMappings("(.*)good(.*)");
2448-
ASSERT_TRUE(mappings.size() == expected_results.size());
2448+
mappings = asset_manager.GetAsMappings("(.*)good(.*)", std::nullopt);
2449+
ASSERT_EQ(mappings.size(), expected_results.size());
2450+
2451+
for (auto& mapping : mappings) {
2452+
std::string result(reinterpret_cast<const char*>(mapping->GetMapping()),
2453+
mapping->GetSize());
2454+
EXPECT_NE(
2455+
std::find(expected_results.begin(), expected_results.end(), result),
2456+
expected_results.end());
2457+
}
2458+
}
2459+
2460+
#if defined(OS_FUCHSIA)
2461+
TEST_F(ShellTest, AssetManagerMultiSubdir) {
2462+
std::string subdir_path = "subdir";
2463+
2464+
fml::ScopedTemporaryDirectory asset_dir;
2465+
fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
2466+
asset_dir.path().c_str(), false, fml::FilePermission::kRead);
2467+
fml::UniqueFD subdir_fd =
2468+
fml::OpenDirectory((asset_dir.path() + "/" + subdir_path).c_str(), true,
2469+
fml::FilePermission::kReadWrite);
2470+
2471+
std::vector<std::string> filenames = {
2472+
"bad0",
2473+
"notgood", // this is to make sure the pattern (.*)good(.*) only matches
2474+
// things in the subdirectory
2475+
};
2476+
2477+
std::vector<std::string> subdir_filenames = {
2478+
"good0",
2479+
"good1",
2480+
"bad1",
2481+
};
2482+
2483+
for (auto filename : filenames) {
2484+
bool success = fml::WriteAtomically(asset_dir_fd, filename.c_str(),
2485+
fml::DataMapping(filename));
2486+
ASSERT_TRUE(success);
2487+
}
2488+
2489+
for (auto filename : subdir_filenames) {
2490+
bool success = fml::WriteAtomically(subdir_fd, filename.c_str(),
2491+
fml::DataMapping(filename));
2492+
ASSERT_TRUE(success);
2493+
}
2494+
2495+
AssetManager asset_manager;
2496+
asset_manager.PushBack(
2497+
std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));
2498+
2499+
auto mappings = asset_manager.GetAsMappings("(.*)", std::nullopt);
2500+
EXPECT_EQ(mappings.size(), 5u);
2501+
2502+
mappings = asset_manager.GetAsMappings("(.*)", subdir_path);
2503+
EXPECT_EQ(mappings.size(), 3u);
2504+
2505+
std::vector<std::string> expected_results = {
2506+
"good0",
2507+
"good1",
2508+
};
2509+
2510+
mappings = asset_manager.GetAsMappings("(.*)good(.*)", subdir_path);
2511+
ASSERT_EQ(mappings.size(), expected_results.size());
24492512

24502513
for (auto& mapping : mappings) {
24512514
std::string result(reinterpret_cast<const char*>(mapping->GetMapping()),
@@ -2455,6 +2518,7 @@ TEST_F(ShellTest, AssetManagerMulti) {
24552518
expected_results.end());
24562519
}
24572520
}
2521+
#endif // OS_FUCHSIA
24582522

24592523
TEST_F(ShellTest, Spawn) {
24602524
auto settings = CreateSettingsForFixture();

shell/platform/fuchsia/flutter/tests/engine_unittests.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,10 @@ TEST_F(EngineTest, SkpWarmup) {
102102
fml::ScopedTemporaryDirectory asset_dir;
103103
fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
104104
asset_dir.path().c_str(), false, fml::FilePermission::kRead);
105+
fml::UniqueFD subdir_fd = fml::OpenDirectory(asset_dir_fd, "shaders", true,
106+
fml::FilePermission::kReadWrite);
105107

106-
bool success = fml::WriteAtomically(asset_dir_fd, "test.skp", mapping);
108+
bool success = fml::WriteAtomically(subdir_fd, "test.skp", mapping);
107109
ASSERT_TRUE(success);
108110

109111
auto asset_manager = std::make_shared<AssetManager>();

0 commit comments

Comments
 (0)