AssetManager2_bench.cpp revision c8f71aa67ea599cb80205496cb67e9e7a121299c
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
31namespace app = com::android::app;
32namespace basic = com::android::basic;
33namespace libclient = com::android::libclient;
34
35namespace android {
36
37constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
38
39static 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}
47BENCHMARK(BM_AssetManagerLoadAssets);
48
49static 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}
60BENCHMARK(BM_AssetManagerLoadAssetsOld);
61
62static 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}
70BENCHMARK(BM_AssetManagerLoadFrameworkAssets);
71
72static 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}
83BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
84
85static 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
116static void BM_AssetManagerGetResource(benchmark::State& state) {
117  GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
118                       basic::R::integer::number1, state);
119}
120BENCHMARK(BM_AssetManagerGetResource);
121
122static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
123  GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
124                          basic::R::integer::number1, state);
125}
126BENCHMARK(BM_AssetManagerGetResourceOld);
127
128static 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}
134BENCHMARK(BM_AssetManagerGetLibraryResource);
135
136static 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}
142BENCHMARK(BM_AssetManagerGetLibraryResourceOld);
143
144constexpr static const uint32_t kStringOkId = 0x0104000au;
145
146static 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}
152BENCHMARK(BM_AssetManagerGetResourceFrameworkLocale);
153
154static 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}
160BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld);
161
162static 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}
183BENCHMARK(BM_AssetManagerGetBag);
184
185static 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}
208BENCHMARK(BM_AssetManagerGetBagOld);
209
210static 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}
226BENCHMARK(BM_AssetManagerGetResourceLocales);
227
228static 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}
244BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
245
246}  // namespace android
247