1 /*
2  * Copyright (C) 2017 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 <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 #include <string>
21 #include <tuple>
22 #include <vector>
23 
24 #include <android-base/test_utils.h>
25 #include <benchmark/benchmark.h>
26 #include <ziparchive/zip_archive.h>
27 #include <ziparchive/zip_archive_stream_entry.h>
28 #include <ziparchive/zip_writer.h>
29 
CreateZip(int size=4,int count=1000)30 static std::unique_ptr<TemporaryFile> CreateZip(int size = 4, int count = 1000) {
31   auto result = std::make_unique<TemporaryFile>();
32   FILE* fp = fdopen(result->fd, "w");
33 
34   ZipWriter writer(fp);
35   std::string lastName = "file";
36   for (size_t i = 0; i < count; i++) {
37     // Make file names longer and longer.
38     lastName = lastName + std::to_string(i);
39     writer.StartEntry(lastName.c_str(), ZipWriter::kCompress);
40     while (size > 0) {
41       writer.WriteBytes("helo", 4);
42       size -= 4;
43     }
44     writer.FinishEntry();
45   }
46   writer.Finish();
47   fclose(fp);
48 
49   return result;
50 }
51 
FindEntry_no_match(benchmark::State & state)52 static void FindEntry_no_match(benchmark::State& state) {
53   // Create a temporary zip archive.
54   std::unique_ptr<TemporaryFile> temp_file(CreateZip());
55   ZipArchiveHandle handle;
56   ZipEntry data;
57 
58   // In order to walk through all file names in the archive, look for a name
59   // that does not exist in the archive.
60   std::string_view name("thisFileNameDoesNotExist");
61 
62   // Start the benchmark.
63   for (auto _ : state) {
64     OpenArchive(temp_file->path, &handle);
65     FindEntry(handle, name, &data);
66     CloseArchive(handle);
67   }
68 }
69 BENCHMARK(FindEntry_no_match);
70 
Iterate_all_files(benchmark::State & state)71 static void Iterate_all_files(benchmark::State& state) {
72   std::unique_ptr<TemporaryFile> temp_file(CreateZip());
73   ZipArchiveHandle handle;
74   void* iteration_cookie;
75   ZipEntry data;
76   std::string name;
77 
78   for (auto _ : state) {
79     OpenArchive(temp_file->path, &handle);
80     StartIteration(handle, &iteration_cookie);
81     while (Next(iteration_cookie, &data, &name) == 0) {
82     }
83     EndIteration(iteration_cookie);
84     CloseArchive(handle);
85   }
86 }
87 BENCHMARK(Iterate_all_files);
88 
StartAlignedEntry(benchmark::State & state)89 static void StartAlignedEntry(benchmark::State& state) {
90   TemporaryFile file;
91   FILE* fp = fdopen(file.fd, "w");
92 
93   ZipWriter writer(fp);
94 
95   auto alignment = uint32_t(state.range(0));
96   std::string name = "name";
97   int counter = 0;
98   for (auto _ : state) {
99     writer.StartAlignedEntry(name + std::to_string(counter++), 0, alignment);
100     state.PauseTiming();
101     writer.WriteBytes("hola", 4);
102     writer.FinishEntry();
103     state.ResumeTiming();
104   }
105 
106   writer.Finish();
107   fclose(fp);
108 }
109 BENCHMARK(StartAlignedEntry)->Arg(2)->Arg(16)->Arg(1024)->Arg(4096);
110 
ExtractEntry(benchmark::State & state)111 static void ExtractEntry(benchmark::State& state) {
112   std::unique_ptr<TemporaryFile> temp_file(CreateZip(1024 * 1024, 1));
113 
114   ZipArchiveHandle handle;
115   ZipEntry data;
116   if (OpenArchive(temp_file->path, &handle)) {
117     state.SkipWithError("Failed to open archive");
118   }
119   if (FindEntry(handle, "file0", &data)) {
120     state.SkipWithError("Failed to find archive entry");
121   }
122 
123   std::vector<uint8_t> buffer(1024 * 1024);
124   for (auto _ : state) {
125     if (ExtractToMemory(handle, &data, buffer.data(), uint32_t(buffer.size()))) {
126       state.SkipWithError("Failed to extract archive entry");
127       break;
128     }
129   }
130   CloseArchive(handle);
131 }
132 
133 BENCHMARK(ExtractEntry)->Arg(2)->Arg(16)->Arg(1024);
134 
135 BENCHMARK_MAIN();
136