blob: 58b7513377ce7b629e0488abbe8140950bf7490b [file] [log] [blame]
Calin Juravle877fd962016-01-05 14:29:29 +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 "compiler/profile_assistant.h"
22#include "jit/offline_profiling_info.h"
23
24namespace art {
25
26class ProfileAssistantTest : public CommonRuntimeTest {
27 protected:
28 void SetupProfile(const std::string& id,
29 uint32_t checksum,
30 uint16_t number_of_methods,
31 const ScratchFile& profile,
32 ProfileCompilationInfo* info,
33 uint16_t start_method_index = 0) {
34 std::string dex_location1 = "location1" + id;
35 uint32_t dex_location_checksum1 = checksum;
36 std::string dex_location2 = "location2" + id;
37 uint32_t dex_location_checksum2 = 10 * checksum;
38 for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) {
39 ASSERT_TRUE(info->AddData(dex_location1, dex_location_checksum1, i));
40 ASSERT_TRUE(info->AddData(dex_location2, dex_location_checksum2, i));
41 }
42 ASSERT_TRUE(info->Save(GetFd(profile)));
43 ASSERT_EQ(0, profile.GetFile()->Flush());
44 ASSERT_TRUE(profile.GetFile()->ResetOffset());
45 }
46
47 uint32_t GetFd(const ScratchFile& file) const {
48 return static_cast<uint32_t>(file.GetFd());
49 }
50};
51
52TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferences) {
53 ScratchFile profile1;
54 ScratchFile profile2;
55 ScratchFile reference_profile1;
56 ScratchFile reference_profile2;
57
58 std::vector<uint32_t> profile_fds({
59 GetFd(profile1),
60 GetFd(profile2)});
61 std::vector<uint32_t> reference_profile_fds({
62 GetFd(reference_profile1),
63 GetFd(reference_profile2)});
64
65 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
66 ProfileCompilationInfo info1;
67 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
68 ProfileCompilationInfo info2;
69 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, profile2, &info2);
70
71 // We should advise compilation.
72 ProfileCompilationInfo* result;
73 ASSERT_TRUE(ProfileAssistant::ProcessProfiles(profile_fds, reference_profile_fds, &result));
74 ASSERT_TRUE(result != nullptr);
75
76 // The resulting compilation info must be equal to the merge of the inputs.
77 ProfileCompilationInfo expected;
78 ASSERT_TRUE(expected.Load(info1));
79 ASSERT_TRUE(expected.Load(info2));
80 ASSERT_TRUE(expected.Equals(*result));
81
82 // The information from profiles must be transfered to the reference profiles.
83 ProfileCompilationInfo file_info1;
84 ASSERT_TRUE(reference_profile1.GetFile()->ResetOffset());
85 ASSERT_TRUE(file_info1.Load(GetFd(reference_profile1)));
86 ASSERT_TRUE(file_info1.Equals(info1));
87
88 ProfileCompilationInfo file_info2;
89 ASSERT_TRUE(reference_profile2.GetFile()->ResetOffset());
90 ASSERT_TRUE(file_info2.Load(GetFd(reference_profile2)));
91 ASSERT_TRUE(file_info2.Equals(info2));
92
93 // Initial profiles must be cleared.
94 ASSERT_EQ(0, profile1.GetFile()->GetLength());
95 ASSERT_EQ(0, profile2.GetFile()->GetLength());
96}
97
98TEST_F(ProfileAssistantTest, AdviseCompilationNonEmptyReferences) {
99 ScratchFile profile1;
100 ScratchFile profile2;
101 ScratchFile reference_profile1;
102 ScratchFile reference_profile2;
103
104 std::vector<uint32_t> profile_fds({
105 GetFd(profile1),
106 GetFd(profile2)});
107 std::vector<uint32_t> reference_profile_fds({
108 GetFd(reference_profile1),
109 GetFd(reference_profile2)});
110
111 // The new profile info will contain the methods with indices 0-100.
112 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
113 ProfileCompilationInfo info1;
114 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
115 ProfileCompilationInfo info2;
116 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, profile2, &info2);
117
118
119 // The reference profile info will contain the methods with indices 50-150.
120 const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
121 ProfileCompilationInfo reference_info1;
122 SetupProfile("p1", 1, kNumberOfMethodsAlreadyCompiled, reference_profile1,
123 &reference_info1, kNumberOfMethodsToEnableCompilation / 2);
124 ProfileCompilationInfo reference_info2;
125 SetupProfile("p2", 2, kNumberOfMethodsAlreadyCompiled, reference_profile2,
126 &reference_info2, kNumberOfMethodsToEnableCompilation / 2);
127
128 // We should advise compilation.
129 ProfileCompilationInfo* result;
130 ASSERT_TRUE(ProfileAssistant::ProcessProfiles(profile_fds, reference_profile_fds, &result));
131 ASSERT_TRUE(result != nullptr);
132
133 // The resulting compilation info must be equal to the merge of the inputs
134 ProfileCompilationInfo expected;
135 ASSERT_TRUE(expected.Load(info1));
136 ASSERT_TRUE(expected.Load(info2));
137 ASSERT_TRUE(expected.Load(reference_info1));
138 ASSERT_TRUE(expected.Load(reference_info2));
139 ASSERT_TRUE(expected.Equals(*result));
140
141 // The information from profiles must be transfered to the reference profiles.
142 ProfileCompilationInfo file_info1;
143 ProfileCompilationInfo merge1;
144 ASSERT_TRUE(merge1.Load(info1));
145 ASSERT_TRUE(merge1.Load(reference_info1));
146 ASSERT_TRUE(reference_profile1.GetFile()->ResetOffset());
147 ASSERT_TRUE(file_info1.Load(GetFd(reference_profile1)));
148 ASSERT_TRUE(file_info1.Equals(merge1));
149
150 ProfileCompilationInfo file_info2;
151 ProfileCompilationInfo merge2;
152 ASSERT_TRUE(merge2.Load(info2));
153 ASSERT_TRUE(merge2.Load(reference_info2));
154 ASSERT_TRUE(reference_profile2.GetFile()->ResetOffset());
155 ASSERT_TRUE(file_info2.Load(GetFd(reference_profile2)));
156 ASSERT_TRUE(file_info2.Equals(merge2));
157
158 // Initial profiles must be cleared.
159 ASSERT_EQ(0, profile1.GetFile()->GetLength());
160 ASSERT_EQ(0, profile2.GetFile()->GetLength());
161}
162
163TEST_F(ProfileAssistantTest, DoNotAdviseCompilation) {
164 ScratchFile profile1;
165 ScratchFile profile2;
166 ScratchFile reference_profile1;
167 ScratchFile reference_profile2;
168
169 std::vector<uint32_t> profile_fds({
170 GetFd(profile1),
171 GetFd(profile2)});
172 std::vector<uint32_t> reference_profile_fds({
173 GetFd(reference_profile1),
174 GetFd(reference_profile2)});
175
176 const uint16_t kNumberOfMethodsToSkipCompilation = 1;
177 ProfileCompilationInfo info1;
178 SetupProfile("p1", 1, kNumberOfMethodsToSkipCompilation, profile1, &info1);
179 ProfileCompilationInfo info2;
180 SetupProfile("p2", 2, kNumberOfMethodsToSkipCompilation, profile2, &info2);
181
182 // We should not advise compilation.
Calin Juravle47c83ea2016-01-20 03:56:12 +0000183 ProfileCompilationInfo* result = nullptr;
Calin Juravle877fd962016-01-05 14:29:29 +0000184 ASSERT_TRUE(ProfileAssistant::ProcessProfiles(profile_fds, reference_profile_fds, &result));
185 ASSERT_TRUE(result == nullptr);
186
187 // The information from profiles must remain the same.
188 ProfileCompilationInfo file_info1;
189 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
190 ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
191 ASSERT_TRUE(file_info1.Equals(info1));
192
193 ProfileCompilationInfo file_info2;
194 ASSERT_TRUE(profile2.GetFile()->ResetOffset());
195 ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
196 ASSERT_TRUE(file_info2.Equals(info2));
197
198 // Reference profile files must remain empty.
199 ASSERT_EQ(0, reference_profile1.GetFile()->GetLength());
200 ASSERT_EQ(0, reference_profile2.GetFile()->GetLength());
201}
202
203TEST_F(ProfileAssistantTest, FailProcessingBecauseOfProfiles) {
204 ScratchFile profile1;
205 ScratchFile profile2;
206 ScratchFile reference_profile1;
207 ScratchFile reference_profile2;
208
209 std::vector<uint32_t> profile_fds({
210 GetFd(profile1),
211 GetFd(profile2)});
212 std::vector<uint32_t> reference_profile_fds({
213 GetFd(reference_profile1),
214 GetFd(reference_profile2)});
215
216 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
217 // Assign different hashes for the same dex file. This will make merging of information to fail.
218 ProfileCompilationInfo info1;
219 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
220 ProfileCompilationInfo info2;
221 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, profile2, &info2);
222
223 // We should fail processing.
Calin Juravle47c83ea2016-01-20 03:56:12 +0000224 ProfileCompilationInfo* result = nullptr;
Calin Juravle877fd962016-01-05 14:29:29 +0000225 ASSERT_FALSE(ProfileAssistant::ProcessProfiles(profile_fds, reference_profile_fds, &result));
226 ASSERT_TRUE(result == nullptr);
227
228 // The information from profiles must still remain the same.
229 ProfileCompilationInfo file_info1;
230 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
231 ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
232 ASSERT_TRUE(file_info1.Equals(info1));
233
234 ProfileCompilationInfo file_info2;
235 ASSERT_TRUE(profile2.GetFile()->ResetOffset());
236 ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
237 ASSERT_TRUE(file_info2.Equals(info2));
238
239 // Reference profile files must still remain empty.
240 ASSERT_EQ(0, reference_profile1.GetFile()->GetLength());
241 ASSERT_EQ(0, reference_profile2.GetFile()->GetLength());
242}
243
244TEST_F(ProfileAssistantTest, FailProcessingBecauseOfReferenceProfiles) {
245 ScratchFile profile1;
246 ScratchFile reference_profile;
247
248 std::vector<uint32_t> profile_fds({
249 GetFd(profile1)});
250 std::vector<uint32_t> reference_profile_fds({
251 GetFd(reference_profile)});
252
253 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
254 // Assign different hashes for the same dex file. This will make merging of information to fail.
255 ProfileCompilationInfo info1;
256 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
257 ProfileCompilationInfo reference_info;
258 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, reference_profile, &reference_info);
259
260 // We should not advise compilation.
Calin Juravle47c83ea2016-01-20 03:56:12 +0000261 ProfileCompilationInfo* result = nullptr;
Calin Juravle877fd962016-01-05 14:29:29 +0000262 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
263 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
264 ASSERT_FALSE(ProfileAssistant::ProcessProfiles(profile_fds, reference_profile_fds, &result));
265 ASSERT_TRUE(result == nullptr);
266
267 // The information from profiles must still remain the same.
268 ProfileCompilationInfo file_info1;
269 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
270 ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
271 ASSERT_TRUE(file_info1.Equals(info1));
272
273 ProfileCompilationInfo file_info2;
274 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
275 ASSERT_TRUE(file_info2.Load(GetFd(reference_profile)));
276 ASSERT_TRUE(file_info2.Equals(reference_info));
277}
278
279} // namespace art