1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "benchmark/benchmark.h"
18
19 #include "android-base/stringprintf.h"
20 #include "androidfw/ApkAssets.h"
21 #include "androidfw/AssetManager.h"
22 #include "androidfw/AssetManager2.h"
23 #include "androidfw/ResourceTypes.h"
24
25 #include "BenchmarkHelpers.h"
26 #include "TestHelpers.h"
27 #include "data/basic/R.h"
28 #include "data/libclient/R.h"
29 #include "data/styles/R.h"
30
31 namespace app = com::android::app;
32 namespace basic = com::android::basic;
33 namespace libclient = com::android::libclient;
34
35 namespace android {
36
37 constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
38
BM_AssetManagerLoadAssets(benchmark::State & state)39 static void BM_AssetManagerLoadAssets(benchmark::State& state) {
40 std::string path = GetTestDataPath() + "/basic/basic.apk";
41 while (state.KeepRunning()) {
42 std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
43 AssetManager2 assets;
44 assets.SetApkAssets({apk.get()});
45 }
46 }
47 BENCHMARK(BM_AssetManagerLoadAssets);
48
BM_AssetManagerLoadAssetsOld(benchmark::State & state)49 static void BM_AssetManagerLoadAssetsOld(benchmark::State& state) {
50 String8 path((GetTestDataPath() + "/basic/basic.apk").data());
51 while (state.KeepRunning()) {
52 AssetManager assets;
53 assets.addAssetPath(path, nullptr /* cookie */, false /* appAsLib */,
54 false /* isSystemAsset */);
55
56 // Force creation.
57 assets.getResources(true);
58 }
59 }
60 BENCHMARK(BM_AssetManagerLoadAssetsOld);
61
BM_AssetManagerLoadFrameworkAssets(benchmark::State & state)62 static void BM_AssetManagerLoadFrameworkAssets(benchmark::State& state) {
63 std::string path = kFrameworkPath;
64 while (state.KeepRunning()) {
65 std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
66 AssetManager2 assets;
67 assets.SetApkAssets({apk.get()});
68 }
69 }
70 BENCHMARK(BM_AssetManagerLoadFrameworkAssets);
71
BM_AssetManagerLoadFrameworkAssetsOld(benchmark::State & state)72 static void BM_AssetManagerLoadFrameworkAssetsOld(benchmark::State& state) {
73 String8 path(kFrameworkPath);
74 while (state.KeepRunning()) {
75 AssetManager assets;
76 assets.addAssetPath(path, nullptr /* cookie */, false /* appAsLib */,
77 false /* isSystemAsset */);
78
79 // Force creation.
80 assets.getResources(true);
81 }
82 }
83 BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
84
GetResourceBenchmark(const std::vector<std::string> & paths,const ResTable_config * config,uint32_t resid,benchmark::State & state)85 static void GetResourceBenchmark(const std::vector<std::string>& paths,
86 const ResTable_config* config, uint32_t resid,
87 benchmark::State& state) {
88 std::vector<std::unique_ptr<const ApkAssets>> apk_assets;
89 std::vector<const ApkAssets*> apk_assets_ptrs;
90 for (const std::string& path : paths) {
91 std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
92 if (apk == nullptr) {
93 state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
94 return;
95 }
96 apk_assets_ptrs.push_back(apk.get());
97 apk_assets.push_back(std::move(apk));
98 }
99
100 AssetManager2 assetmanager;
101 assetmanager.SetApkAssets(apk_assets_ptrs);
102 if (config != nullptr) {
103 assetmanager.SetConfiguration(*config);
104 }
105
106 Res_value value;
107 ResTable_config selected_config;
108 uint32_t flags;
109
110 while (state.KeepRunning()) {
111 assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
112 &selected_config, &flags);
113 }
114 }
115
BM_AssetManagerGetResource(benchmark::State & state)116 static void BM_AssetManagerGetResource(benchmark::State& state) {
117 GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
118 basic::R::integer::number1, state);
119 }
120 BENCHMARK(BM_AssetManagerGetResource);
121
BM_AssetManagerGetResourceOld(benchmark::State & state)122 static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
123 GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
124 basic::R::integer::number1, state);
125 }
126 BENCHMARK(BM_AssetManagerGetResourceOld);
127
BM_AssetManagerGetLibraryResource(benchmark::State & state)128 static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
129 GetResourceBenchmark(
130 {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
131 GetTestDataPath() + "/libclient/libclient.apk"},
132 nullptr /*config*/, libclient::R::string::foo_one, state);
133 }
134 BENCHMARK(BM_AssetManagerGetLibraryResource);
135
BM_AssetManagerGetLibraryResourceOld(benchmark::State & state)136 static void BM_AssetManagerGetLibraryResourceOld(benchmark::State& state) {
137 GetResourceBenchmarkOld(
138 {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
139 GetTestDataPath() + "/libclient/libclient.apk"},
140 nullptr /*config*/, libclient::R::string::foo_one, state);
141 }
142 BENCHMARK(BM_AssetManagerGetLibraryResourceOld);
143
144 constexpr static const uint32_t kStringOkId = 0x0104000au;
145
BM_AssetManagerGetResourceFrameworkLocale(benchmark::State & state)146 static void BM_AssetManagerGetResourceFrameworkLocale(benchmark::State& state) {
147 ResTable_config config;
148 memset(&config, 0, sizeof(config));
149 memcpy(config.language, "fr", 2);
150 GetResourceBenchmark({kFrameworkPath}, &config, kStringOkId, state);
151 }
152 BENCHMARK(BM_AssetManagerGetResourceFrameworkLocale);
153
BM_AssetManagerGetResourceFrameworkLocaleOld(benchmark::State & state)154 static void BM_AssetManagerGetResourceFrameworkLocaleOld(benchmark::State& state) {
155 ResTable_config config;
156 memset(&config, 0, sizeof(config));
157 memcpy(config.language, "fr", 2);
158 GetResourceBenchmarkOld({kFrameworkPath}, &config, kStringOkId, state);
159 }
160 BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld);
161
BM_AssetManagerGetBag(benchmark::State & state)162 static void BM_AssetManagerGetBag(benchmark::State& state) {
163 std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
164 if (apk == nullptr) {
165 state.SkipWithError("Failed to load assets");
166 return;
167 }
168
169 AssetManager2 assets;
170 assets.SetApkAssets({apk.get()});
171
172 while (state.KeepRunning()) {
173 const ResolvedBag* bag = assets.GetBag(app::R::style::StyleTwo);
174 const auto bag_end = end(bag);
175 for (auto iter = begin(bag); iter != bag_end; ++iter) {
176 uint32_t key = iter->key;
177 Res_value value = iter->value;
178 benchmark::DoNotOptimize(key);
179 benchmark::DoNotOptimize(value);
180 }
181 }
182 }
183 BENCHMARK(BM_AssetManagerGetBag);
184
BM_AssetManagerGetBagOld(benchmark::State & state)185 static void BM_AssetManagerGetBagOld(benchmark::State& state) {
186 AssetManager assets;
187 if (!assets.addAssetPath(String8((GetTestDataPath() + "/styles/styles.apk").data()),
188 nullptr /*cookie*/, false /*appAsLib*/, false /*isSystemAssets*/)) {
189 state.SkipWithError("Failed to load assets");
190 return;
191 }
192
193 const ResTable& table = assets.getResources(true);
194
195 while (state.KeepRunning()) {
196 const ResTable::bag_entry* bag_begin;
197 const ssize_t N = table.lockBag(app::R::style::StyleTwo, &bag_begin);
198 const ResTable::bag_entry* const bag_end = bag_begin + N;
199 for (auto iter = bag_begin; iter != bag_end; ++iter) {
200 uint32_t key = iter->map.name.ident;
201 Res_value value = iter->map.value;
202 benchmark::DoNotOptimize(key);
203 benchmark::DoNotOptimize(value);
204 }
205 table.unlockBag(bag_begin);
206 }
207 }
208 BENCHMARK(BM_AssetManagerGetBagOld);
209
BM_AssetManagerGetResourceLocales(benchmark::State & state)210 static void BM_AssetManagerGetResourceLocales(benchmark::State& state) {
211 std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
212 if (apk == nullptr) {
213 state.SkipWithError("Failed to load assets");
214 return;
215 }
216
217 AssetManager2 assets;
218 assets.SetApkAssets({apk.get()});
219
220 while (state.KeepRunning()) {
221 std::set<std::string> locales =
222 assets.GetResourceLocales(false /*exclude_system*/, true /*merge_equivalent_languages*/);
223 benchmark::DoNotOptimize(locales);
224 }
225 }
226 BENCHMARK(BM_AssetManagerGetResourceLocales);
227
BM_AssetManagerGetResourceLocalesOld(benchmark::State & state)228 static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) {
229 AssetManager assets;
230 if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
231 false /*isSystemAssets*/)) {
232 state.SkipWithError("Failed to load assets");
233 return;
234 }
235
236 const ResTable& table = assets.getResources(true);
237
238 while (state.KeepRunning()) {
239 Vector<String8> locales;
240 table.getLocales(&locales, true /*includeSystemLocales*/, true /*mergeEquivalentLangs*/);
241 benchmark::DoNotOptimize(locales);
242 }
243 }
244 BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
245
246 } // namespace android
247