blob: 543be5d18182066930a537ae1b72b10c798732a8 [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,
32 const ScratchFile& profile,
33 ProfileCompilationInfo* info,
34 uint16_t start_method_index = 0) {
35 std::string dex_location1 = "location1" + id;
36 uint32_t dex_location_checksum1 = checksum;
37 std::string dex_location2 = "location2" + id;
38 uint32_t dex_location_checksum2 = 10 * checksum;
39 for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) {
40 ASSERT_TRUE(info->AddData(dex_location1, dex_location_checksum1, i));
41 ASSERT_TRUE(info->AddData(dex_location2, dex_location_checksum2, i));
42 }
43 ASSERT_TRUE(info->Save(GetFd(profile)));
44 ASSERT_EQ(0, profile.GetFile()->Flush());
45 ASSERT_TRUE(profile.GetFile()->ResetOffset());
46 }
47
48 int GetFd(const ScratchFile& file) const {
49 return static_cast<int>(file.GetFd());
50 }
51
52 void CheckProfileInfo(ScratchFile& file, const ProfileCompilationInfo& info) {
53 ProfileCompilationInfo file_info;
54 ASSERT_TRUE(file.GetFile()->ResetOffset());
55 ASSERT_TRUE(file_info.Load(GetFd(file)));
56 ASSERT_TRUE(file_info.Equals(info));
57 }
58
59 // Runs test with given arguments.
60 int ProcessProfiles(const std::vector<int>& profiles_fd, int reference_profile_fd) {
61 std::string file_path = GetTestAndroidRoot();
62 if (IsHost()) {
63 file_path += "/bin/profman";
64 } else {
65 file_path += "/xbin/profman";
66 }
67 if (kIsDebugBuild) {
68 file_path += "d";
69 }
70
71 EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
72 std::vector<std::string> argv_str;
73 argv_str.push_back(file_path);
74 for (size_t k = 0; k < profiles_fd.size(); k++) {
75 argv_str.push_back("--profile-file-fd=" + std::to_string(profiles_fd[k]));
76 }
77 argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile_fd));
78
79 std::string error;
80 return ExecAndReturnCode(argv_str, &error);
81 }
82};
83
84TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferences) {
85 ScratchFile profile1;
86 ScratchFile profile2;
87 ScratchFile reference_profile;
88
89 std::vector<int> profile_fds({
90 GetFd(profile1),
91 GetFd(profile2)});
92 int reference_profile_fd = GetFd(reference_profile);
93
94 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
95 ProfileCompilationInfo info1;
96 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
97 ProfileCompilationInfo info2;
98 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, profile2, &info2);
99
100 // We should advise compilation.
101 ASSERT_EQ(ProfileAssistant::kCompile,
102 ProcessProfiles(profile_fds, reference_profile_fd));
103 // The resulting compilation info must be equal to the merge of the inputs.
104 ProfileCompilationInfo result;
105 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
106 ASSERT_TRUE(result.Load(reference_profile_fd));
107
108 ProfileCompilationInfo expected;
109 ASSERT_TRUE(expected.Load(info1));
110 ASSERT_TRUE(expected.Load(info2));
111 ASSERT_TRUE(expected.Equals(result));
112
113 // The information from profiles must remain the same.
114 CheckProfileInfo(profile1, info1);
115 CheckProfileInfo(profile2, info2);
116}
117
118TEST_F(ProfileAssistantTest, AdviseCompilationNonEmptyReferences) {
119 ScratchFile profile1;
120 ScratchFile profile2;
121 ScratchFile reference_profile;
122
123 std::vector<int> profile_fds({
124 GetFd(profile1),
125 GetFd(profile2)});
126 int reference_profile_fd = GetFd(reference_profile);
127
128 // The new profile info will contain the methods with indices 0-100.
129 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
130 ProfileCompilationInfo info1;
131 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
132 ProfileCompilationInfo info2;
133 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, profile2, &info2);
134
135
136 // The reference profile info will contain the methods with indices 50-150.
137 const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
138 ProfileCompilationInfo reference_info;
139 SetupProfile("p1", 1, kNumberOfMethodsAlreadyCompiled, reference_profile,
140 &reference_info, kNumberOfMethodsToEnableCompilation / 2);
141
142 // We should advise compilation.
143 ASSERT_EQ(ProfileAssistant::kCompile,
144 ProcessProfiles(profile_fds, reference_profile_fd));
145
146 // The resulting compilation info must be equal to the merge of the inputs
147 ProfileCompilationInfo result;
148 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
149 ASSERT_TRUE(result.Load(reference_profile_fd));
150
151 ProfileCompilationInfo expected;
152 ASSERT_TRUE(expected.Load(info1));
153 ASSERT_TRUE(expected.Load(info2));
154 ASSERT_TRUE(expected.Load(reference_info));
155 ASSERT_TRUE(expected.Equals(result));
156
157 // The information from profiles must remain the same.
158 CheckProfileInfo(profile1, info1);
159 CheckProfileInfo(profile2, info2);
160}
161
162TEST_F(ProfileAssistantTest, DoNotAdviseCompilation) {
163 ScratchFile profile1;
164 ScratchFile profile2;
165 ScratchFile reference_profile;
166
167 std::vector<int> profile_fds({
168 GetFd(profile1),
169 GetFd(profile2)});
170 int reference_profile_fd = GetFd(reference_profile);
171
172 const uint16_t kNumberOfMethodsToSkipCompilation = 1;
173 ProfileCompilationInfo info1;
174 SetupProfile("p1", 1, kNumberOfMethodsToSkipCompilation, profile1, &info1);
175 ProfileCompilationInfo info2;
176 SetupProfile("p2", 2, kNumberOfMethodsToSkipCompilation, profile2, &info2);
177
178 // We should not advise compilation.
179 ASSERT_EQ(ProfileAssistant::kSkipCompilation,
180 ProcessProfiles(profile_fds, reference_profile_fd));
181
182 // The information from profiles must remain the same.
183 ProfileCompilationInfo file_info1;
184 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
185 ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
186 ASSERT_TRUE(file_info1.Equals(info1));
187
188 ProfileCompilationInfo file_info2;
189 ASSERT_TRUE(profile2.GetFile()->ResetOffset());
190 ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
191 ASSERT_TRUE(file_info2.Equals(info2));
192
193 // Reference profile files must remain empty.
194 ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
195
196 // The information from profiles must remain the same.
197 CheckProfileInfo(profile1, info1);
198 CheckProfileInfo(profile2, info2);
199}
200
201TEST_F(ProfileAssistantTest, FailProcessingBecauseOfProfiles) {
202 ScratchFile profile1;
203 ScratchFile profile2;
204 ScratchFile reference_profile;
205
206 std::vector<int> profile_fds({
207 GetFd(profile1),
208 GetFd(profile2)});
209 int reference_profile_fd = GetFd(reference_profile);
210
211 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
212 // Assign different hashes for the same dex file. This will make merging of information to fail.
213 ProfileCompilationInfo info1;
214 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
215 ProfileCompilationInfo info2;
216 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, profile2, &info2);
217
218 // We should fail processing.
219 ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
220 ProcessProfiles(profile_fds, reference_profile_fd));
221
222 // The information from profiles must remain the same.
223 CheckProfileInfo(profile1, info1);
224 CheckProfileInfo(profile2, info2);
225
226 // Reference profile files must still remain empty.
227 ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
228}
229
230TEST_F(ProfileAssistantTest, FailProcessingBecauseOfReferenceProfiles) {
231 ScratchFile profile1;
232 ScratchFile reference_profile;
233
234 std::vector<int> profile_fds({
235 GetFd(profile1)});
236 int reference_profile_fd = GetFd(reference_profile);
237
238 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
239 // Assign different hashes for the same dex file. This will make merging of information to fail.
240 ProfileCompilationInfo info1;
241 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, profile1, &info1);
242 ProfileCompilationInfo reference_info;
243 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, reference_profile, &reference_info);
244
245 // We should not advise compilation.
246 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
247 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
248 ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
249 ProcessProfiles(profile_fds, reference_profile_fd));
250
251 // The information from profiles must remain the same.
252 CheckProfileInfo(profile1, info1);
253}
254
255} // namespace art