blob: 462c39735ec373e608f9184f3c9b8a53256d8a5f [file] [log] [blame]
Calin Juravle2e2db782016-02-23 12:00:03 +00001/*
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 <gtest/gtest.h>
18
19#include "base/unix_file/fd_file.h"
20#include "common_runtime_test.h"
21#include "profile_assistant.h"
22#include "jit/offline_profiling_info.h"
23#include "utils.h"
24
25namespace art {
26
27class ProfileAssistantTest : public CommonRuntimeTest {
28 protected:
29 void SetupProfile(const std::string& id,
30 uint32_t checksum,
31 uint16_t number_of_methods,
Calin Juravlec824b512016-03-29 20:33:33 +010032 uint16_t number_of_classes,
Calin Juravle2e2db782016-02-23 12:00:03 +000033 const ScratchFile& profile,
34 ProfileCompilationInfo* info,
35 uint16_t start_method_index = 0) {
36 std::string dex_location1 = "location1" + id;
37 uint32_t dex_location_checksum1 = checksum;
38 std::string dex_location2 = "location2" + id;
39 uint32_t dex_location_checksum2 = 10 * checksum;
40 for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) {
Mathieu Chartierc5dd3192015-12-09 16:38:30 -080041 ASSERT_TRUE(info->AddMethodIndex(dex_location1, dex_location_checksum1, i));
42 ASSERT_TRUE(info->AddMethodIndex(dex_location2, dex_location_checksum2, i));
Calin Juravle2e2db782016-02-23 12:00:03 +000043 }
Calin Juravlec824b512016-03-29 20:33:33 +010044 for (uint16_t i = 0; i < number_of_classes; i++) {
45 ASSERT_TRUE(info->AddClassIndex(dex_location1, dex_location_checksum1, i));
46 }
47
Calin Juravle2e2db782016-02-23 12:00:03 +000048 ASSERT_TRUE(info->Save(GetFd(profile)));
49 ASSERT_EQ(0, profile.GetFile()->Flush());
50 ASSERT_TRUE(profile.GetFile()->ResetOffset());
51 }
52
53 int GetFd(const ScratchFile& file) const {
54 return static_cast<int>(file.GetFd());
55 }
56
57 void CheckProfileInfo(ScratchFile& file, const ProfileCompilationInfo& info) {
58 ProfileCompilationInfo file_info;
59 ASSERT_TRUE(file.GetFile()->ResetOffset());
60 ASSERT_TRUE(file_info.Load(GetFd(file)));
61 ASSERT_TRUE(file_info.Equals(info));
62 }
63
64 // Runs test with given arguments.
65 int ProcessProfiles(const std::vector<int>& profiles_fd, int reference_profile_fd) {
66 std::string file_path = GetTestAndroidRoot();
Calin Juravlede4fb632016-02-23 16:53:30 +000067 file_path += "/bin/profman";
Calin Juravle2e2db782016-02-23 12:00:03 +000068 if (kIsDebugBuild) {
69 file_path += "d";
70 }
71
72 EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
73 std::vector<std::string> argv_str;
74 argv_str.push_back(file_path);
75 for (size_t k = 0; k < profiles_fd.size(); k++) {
76 argv_str.push_back("--profile-file-fd=" + std::to_string(profiles_fd[k]));
77 }
78 argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile_fd));
79
80 std::string error;
81 return ExecAndReturnCode(argv_str, &error);
82 }
83};
84
85TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferences) {
86 ScratchFile profile1;
87 ScratchFile profile2;
88 ScratchFile reference_profile;
89
90 std::vector<int> profile_fds({
91 GetFd(profile1),
92 GetFd(profile2)});
93 int reference_profile_fd = GetFd(reference_profile);
94
95 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
96 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +010097 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +000098 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +010099 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000100
101 // We should advise compilation.
102 ASSERT_EQ(ProfileAssistant::kCompile,
103 ProcessProfiles(profile_fds, reference_profile_fd));
104 // The resulting compilation info must be equal to the merge of the inputs.
105 ProfileCompilationInfo result;
106 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
107 ASSERT_TRUE(result.Load(reference_profile_fd));
108
109 ProfileCompilationInfo expected;
Calin Juravle67265462016-03-18 16:23:40 +0000110 ASSERT_TRUE(expected.MergeWith(info1));
111 ASSERT_TRUE(expected.MergeWith(info2));
Calin Juravle2e2db782016-02-23 12:00:03 +0000112 ASSERT_TRUE(expected.Equals(result));
113
114 // The information from profiles must remain the same.
115 CheckProfileInfo(profile1, info1);
116 CheckProfileInfo(profile2, info2);
117}
118
Calin Juravlec824b512016-03-29 20:33:33 +0100119// TODO(calin): Add more tests for classes.
120TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferencesBecauseOfClasses) {
121 ScratchFile profile1;
122 ScratchFile reference_profile;
123
124 std::vector<int> profile_fds({
125 GetFd(profile1)});
126 int reference_profile_fd = GetFd(reference_profile);
127
128 const uint16_t kNumberOfClassesToEnableCompilation = 100;
129 ProfileCompilationInfo info1;
130 SetupProfile("p1", 1, 0, kNumberOfClassesToEnableCompilation, profile1, &info1);
131
132 // We should advise compilation.
133 ASSERT_EQ(ProfileAssistant::kCompile,
134 ProcessProfiles(profile_fds, reference_profile_fd));
135 // The resulting compilation info must be equal to the merge of the inputs.
136 ProfileCompilationInfo result;
137 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
138 ASSERT_TRUE(result.Load(reference_profile_fd));
139
140 ProfileCompilationInfo expected;
141 ASSERT_TRUE(expected.MergeWith(info1));
142 ASSERT_TRUE(expected.Equals(result));
143
144 // The information from profiles must remain the same.
145 CheckProfileInfo(profile1, info1);
146}
147
Calin Juravle2e2db782016-02-23 12:00:03 +0000148TEST_F(ProfileAssistantTest, AdviseCompilationNonEmptyReferences) {
149 ScratchFile profile1;
150 ScratchFile profile2;
151 ScratchFile reference_profile;
152
153 std::vector<int> profile_fds({
154 GetFd(profile1),
155 GetFd(profile2)});
156 int reference_profile_fd = GetFd(reference_profile);
157
158 // The new profile info will contain the methods with indices 0-100.
159 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
160 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100161 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000162 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +0100163 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000164
165
166 // The reference profile info will contain the methods with indices 50-150.
167 const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
168 ProfileCompilationInfo reference_info;
Calin Juravlec824b512016-03-29 20:33:33 +0100169 SetupProfile("p1", 1, kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
Calin Juravle2e2db782016-02-23 12:00:03 +0000170 &reference_info, kNumberOfMethodsToEnableCompilation / 2);
171
172 // We should advise compilation.
173 ASSERT_EQ(ProfileAssistant::kCompile,
174 ProcessProfiles(profile_fds, reference_profile_fd));
175
176 // The resulting compilation info must be equal to the merge of the inputs
177 ProfileCompilationInfo result;
178 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
179 ASSERT_TRUE(result.Load(reference_profile_fd));
180
181 ProfileCompilationInfo expected;
Calin Juravle67265462016-03-18 16:23:40 +0000182 ASSERT_TRUE(expected.MergeWith(info1));
183 ASSERT_TRUE(expected.MergeWith(info2));
184 ASSERT_TRUE(expected.MergeWith(reference_info));
Calin Juravle2e2db782016-02-23 12:00:03 +0000185 ASSERT_TRUE(expected.Equals(result));
186
187 // The information from profiles must remain the same.
188 CheckProfileInfo(profile1, info1);
189 CheckProfileInfo(profile2, info2);
190}
191
192TEST_F(ProfileAssistantTest, DoNotAdviseCompilation) {
193 ScratchFile profile1;
194 ScratchFile profile2;
195 ScratchFile reference_profile;
196
197 std::vector<int> profile_fds({
198 GetFd(profile1),
199 GetFd(profile2)});
200 int reference_profile_fd = GetFd(reference_profile);
201
202 const uint16_t kNumberOfMethodsToSkipCompilation = 1;
203 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100204 SetupProfile("p1", 1, kNumberOfMethodsToSkipCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000205 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +0100206 SetupProfile("p2", 2, kNumberOfMethodsToSkipCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000207
208 // We should not advise compilation.
209 ASSERT_EQ(ProfileAssistant::kSkipCompilation,
210 ProcessProfiles(profile_fds, reference_profile_fd));
211
212 // The information from profiles must remain the same.
213 ProfileCompilationInfo file_info1;
214 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
215 ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
216 ASSERT_TRUE(file_info1.Equals(info1));
217
218 ProfileCompilationInfo file_info2;
219 ASSERT_TRUE(profile2.GetFile()->ResetOffset());
220 ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
221 ASSERT_TRUE(file_info2.Equals(info2));
222
223 // Reference profile files must remain empty.
224 ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
225
226 // The information from profiles must remain the same.
227 CheckProfileInfo(profile1, info1);
228 CheckProfileInfo(profile2, info2);
229}
230
231TEST_F(ProfileAssistantTest, FailProcessingBecauseOfProfiles) {
232 ScratchFile profile1;
233 ScratchFile profile2;
234 ScratchFile reference_profile;
235
236 std::vector<int> profile_fds({
237 GetFd(profile1),
238 GetFd(profile2)});
239 int reference_profile_fd = GetFd(reference_profile);
240
241 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
242 // Assign different hashes for the same dex file. This will make merging of information to fail.
243 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100244 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000245 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +0100246 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000247
248 // We should fail processing.
249 ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
250 ProcessProfiles(profile_fds, reference_profile_fd));
251
252 // The information from profiles must remain the same.
253 CheckProfileInfo(profile1, info1);
254 CheckProfileInfo(profile2, info2);
255
256 // Reference profile files must still remain empty.
257 ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
258}
259
260TEST_F(ProfileAssistantTest, FailProcessingBecauseOfReferenceProfiles) {
261 ScratchFile profile1;
262 ScratchFile reference_profile;
263
264 std::vector<int> profile_fds({
265 GetFd(profile1)});
266 int reference_profile_fd = GetFd(reference_profile);
267
268 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
269 // Assign different hashes for the same dex file. This will make merging of information to fail.
270 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100271 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000272 ProfileCompilationInfo reference_info;
Calin Juravlec824b512016-03-29 20:33:33 +0100273 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, reference_profile, &reference_info);
Calin Juravle2e2db782016-02-23 12:00:03 +0000274
275 // We should not advise compilation.
276 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
277 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
278 ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
279 ProcessProfiles(profile_fds, reference_profile_fd));
280
281 // The information from profiles must remain the same.
282 CheckProfileInfo(profile1, info1);
283}
284
285} // namespace art