AssetManager2_bench.cpp revision 0c40524953f3d36a880f91183302a2ea5c722930
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 "TestHelpers.h"
26#include "data/basic/R.h"
27#include "data/libclient/R.h"
28#include "data/styles/R.h"
29
30namespace app = com::android::app;
31namespace basic = com::android::basic;
32namespace libclient = com::android::libclient;
33
34namespace android {
35
36constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
37
38static void BM_AssetManagerLoadAssets(benchmark::State& state) {
39  std::string path = GetTestDataPath() + "/basic/basic.apk";
40  while (state.KeepRunning()) {
41    std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
42    AssetManager2 assets;
43    assets.SetApkAssets({apk.get()});
44  }
45}
46BENCHMARK(BM_AssetManagerLoadAssets);
47
48static void BM_AssetManagerLoadAssetsOld(benchmark::State& state) {
49  String8 path((GetTestDataPath() + "/basic/basic.apk").data());
50  while (state.KeepRunning()) {
51    AssetManager assets;
52    assets.addAssetPath(path, nullptr /* cookie */, false /* appAsLib */,
53                        false /* isSystemAsset */);
54
55    // Force creation.
56    assets.getResources(true);
57  }
58}
59BENCHMARK(BM_AssetManagerLoadAssetsOld);
60
61static void BM_AssetManagerLoadFrameworkAssets(benchmark::State& state) {
62  std::string path = kFrameworkPath;
63  while (state.KeepRunning()) {
64    std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
65    AssetManager2 assets;
66    assets.SetApkAssets({apk.get()});
67  }
68}
69BENCHMARK(BM_AssetManagerLoadFrameworkAssets);
70
71static void BM_AssetManagerLoadFrameworkAssetsOld(benchmark::State& state) {
72  String8 path(kFrameworkPath);
73  while (state.KeepRunning()) {
74    AssetManager assets;
75    assets.addAssetPath(path, nullptr /* cookie */, false /* appAsLib */,
76                        false /* isSystemAsset */);
77
78    // Force creation.
79    assets.getResources(true);
80  }
81}
82BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
83
84static void GetResourceBenchmark(const std::vector<std::string>& paths,
85                                 const ResTable_config* config, uint32_t resid,
86                                 benchmark::State& state) {
87  std::vector<std::unique_ptr<const ApkAssets>> apk_assets;
88  std::vector<const ApkAssets*> apk_assets_ptrs;
89  for (const std::string& path : paths) {
90    std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
91    if (apk == nullptr) {
92      state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
93      return;
94    }
95    apk_assets_ptrs.push_back(apk.get());
96    apk_assets.push_back(std::move(apk));
97  }
98
99  AssetManager2 assetmanager;
100  assetmanager.SetApkAssets(apk_assets_ptrs);
101  if (config != nullptr) {
102    assetmanager.SetConfiguration(*config);
103  }
104
105  Res_value value;
106  ResTable_config selected_config;
107  uint32_t flags;
108
109  while (state.KeepRunning()) {
110    assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
111                             &selected_config, &flags);
112  }
113}
114
115static void GetResourceBenchmarkOld(const std::vector<std::string>& paths,
116                                    const ResTable_config* config, uint32_t resid,
117                                    benchmark::State& state) {
118  AssetManager assetmanager;
119  for (const std::string& path : paths) {
120    if (!assetmanager.addAssetPath(String8(path.c_str()), nullptr /* cookie */,
121                                   false /* appAsLib */, false /* isSystemAssets */)) {
122      state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
123      return;
124    }
125  }
126
127  if (config != nullptr) {
128    assetmanager.setConfiguration(*config);
129  }
130
131  const ResTable& table = assetmanager.getResources(true);
132
133  Res_value value;
134  ResTable_config selected_config;
135  uint32_t flags;
136
137  while (state.KeepRunning()) {
138    table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
139                      &selected_config);
140  }
141}
142
143static void BM_AssetManagerGetResource(benchmark::State& state) {
144  GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
145                       basic::R::integer::number1, state);
146}
147BENCHMARK(BM_AssetManagerGetResource);
148
149static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
150  GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
151                          basic::R::integer::number1, state);
152}
153BENCHMARK(BM_AssetManagerGetResourceOld);
154
155static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
156  GetResourceBenchmark(
157      {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
158       GetTestDataPath() + "/libclient/libclient.apk"},
159      nullptr /*config*/, libclient::R::string::foo_one, state);
160}
161BENCHMARK(BM_AssetManagerGetLibraryResource);
162
163static void BM_AssetManagerGetLibraryResourceOld(benchmark::State& state) {
164  GetResourceBenchmarkOld(
165      {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
166       GetTestDataPath() + "/libclient/libclient.apk"},
167      nullptr /*config*/, libclient::R::string::foo_one, state);
168}
169BENCHMARK(BM_AssetManagerGetLibraryResourceOld);
170
171constexpr static const uint32_t kStringOkId = 0x0104000au;
172
173static void BM_AssetManagerGetResourceFrameworkLocale(benchmark::State& state) {
174  ResTable_config config;
175  memset(&config, 0, sizeof(config));
176  memcpy(config.language, "fr", 2);
177  GetResourceBenchmark({kFrameworkPath}, &config, kStringOkId, state);
178}
179BENCHMARK(BM_AssetManagerGetResourceFrameworkLocale);
180
181static void BM_AssetManagerGetResourceFrameworkLocaleOld(benchmark::State& state) {
182  ResTable_config config;
183  memset(&config, 0, sizeof(config));
184  memcpy(config.language, "fr", 2);
185  GetResourceBenchmarkOld({kFrameworkPath}, &config, kStringOkId, state);
186}
187BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld);
188
189static void BM_AssetManagerGetBag(benchmark::State& state) {
190  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
191  if (apk == nullptr) {
192    state.SkipWithError("Failed to load assets");
193    return;
194  }
195
196  AssetManager2 assets;
197  assets.SetApkAssets({apk.get()});
198
199  while (state.KeepRunning()) {
200    const ResolvedBag* bag = assets.GetBag(app::R::style::StyleTwo);
201    const auto bag_end = end(bag);
202    for (auto iter = begin(bag); iter != bag_end; ++iter) {
203      uint32_t key = iter->key;
204      Res_value value = iter->value;
205      benchmark::DoNotOptimize(key);
206      benchmark::DoNotOptimize(value);
207    }
208  }
209}
210BENCHMARK(BM_AssetManagerGetBag);
211
212static void BM_AssetManagerGetBagOld(benchmark::State& state) {
213  AssetManager assets;
214  if (!assets.addAssetPath(String8((GetTestDataPath() + "/styles/styles.apk").data()),
215                           nullptr /*cookie*/, false /*appAsLib*/, false /*isSystemAssets*/)) {
216    state.SkipWithError("Failed to load assets");
217    return;
218  }
219
220  const ResTable& table = assets.getResources(true);
221
222  while (state.KeepRunning()) {
223    const ResTable::bag_entry* bag_begin;
224    const ssize_t N = table.lockBag(app::R::style::StyleTwo, &bag_begin);
225    const ResTable::bag_entry* const bag_end = bag_begin + N;
226    for (auto iter = bag_begin; iter != bag_end; ++iter) {
227      uint32_t key = iter->map.name.ident;
228      Res_value value = iter->map.value;
229      benchmark::DoNotOptimize(key);
230      benchmark::DoNotOptimize(value);
231    }
232    table.unlockBag(bag_begin);
233  }
234}
235BENCHMARK(BM_AssetManagerGetBagOld);
236
237static void BM_AssetManagerGetResourceLocales(benchmark::State& state) {
238  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
239  if (apk == nullptr) {
240    state.SkipWithError("Failed to load assets");
241    return;
242  }
243
244  AssetManager2 assets;
245  assets.SetApkAssets({apk.get()});
246
247  while (state.KeepRunning()) {
248    std::set<std::string> locales =
249        assets.GetResourceLocales(false /*exclude_system*/, true /*merge_equivalent_languages*/);
250    benchmark::DoNotOptimize(locales);
251  }
252}
253BENCHMARK(BM_AssetManagerGetResourceLocales);
254
255static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) {
256  AssetManager assets;
257  if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
258                           false /*isSystemAssets*/)) {
259    state.SkipWithError("Failed to load assets");
260    return;
261  }
262
263  const ResTable& table = assets.getResources(true);
264
265  while (state.KeepRunning()) {
266    Vector<String8> locales;
267    table.getLocales(&locales, true /*includeSystemLocales*/, true /*mergeEquivalentLangs*/);
268    benchmark::DoNotOptimize(locales);
269  }
270}
271BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
272
273}  // namespace android
274