• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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 
25 namespace art {
26 
27 class ProfileAssistantTest : public CommonRuntimeTest {
28  protected:
SetupProfile(const std::string & id,uint32_t checksum,uint16_t number_of_methods,uint16_t number_of_classes,const ScratchFile & profile,ProfileCompilationInfo * info,uint16_t start_method_index=0)29   void SetupProfile(const std::string& id,
30                     uint32_t checksum,
31                     uint16_t number_of_methods,
32                     uint16_t number_of_classes,
33                     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++) {
41       ASSERT_TRUE(info->AddMethodIndex(dex_location1, dex_location_checksum1, i));
42       ASSERT_TRUE(info->AddMethodIndex(dex_location2, dex_location_checksum2, i));
43     }
44     for (uint16_t i = 0; i < number_of_classes; i++) {
45       ASSERT_TRUE(info->AddClassIndex(dex_location1, dex_location_checksum1, i));
46     }
47 
48     ASSERT_TRUE(info->Save(GetFd(profile)));
49     ASSERT_EQ(0, profile.GetFile()->Flush());
50     ASSERT_TRUE(profile.GetFile()->ResetOffset());
51   }
52 
GetFd(const ScratchFile & file) const53   int GetFd(const ScratchFile& file) const {
54     return static_cast<int>(file.GetFd());
55   }
56 
CheckProfileInfo(ScratchFile & file,const ProfileCompilationInfo & info)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.
ProcessProfiles(const std::vector<int> & profiles_fd,int reference_profile_fd)65   int ProcessProfiles(const std::vector<int>& profiles_fd, int reference_profile_fd) {
66     std::string file_path = GetTestAndroidRoot();
67     file_path += "/bin/profman";
68     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 
TEST_F(ProfileAssistantTest,AdviseCompilationEmptyReferences)85 TEST_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;
97   SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
98   ProfileCompilationInfo info2;
99   SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
100 
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;
110   ASSERT_TRUE(expected.MergeWith(info1));
111   ASSERT_TRUE(expected.MergeWith(info2));
112   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 
119 // TODO(calin): Add more tests for classes.
TEST_F(ProfileAssistantTest,AdviseCompilationEmptyReferencesBecauseOfClasses)120 TEST_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 
TEST_F(ProfileAssistantTest,AdviseCompilationNonEmptyReferences)148 TEST_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;
161   SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
162   ProfileCompilationInfo info2;
163   SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
164 
165 
166   // The reference profile info will contain the methods with indices 50-150.
167   const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
168   ProfileCompilationInfo reference_info;
169   SetupProfile("p1", 1, kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
170       &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;
182   ASSERT_TRUE(expected.MergeWith(info1));
183   ASSERT_TRUE(expected.MergeWith(info2));
184   ASSERT_TRUE(expected.MergeWith(reference_info));
185   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 
TEST_F(ProfileAssistantTest,DoNotAdviseCompilation)192 TEST_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;
204   SetupProfile("p1", 1, kNumberOfMethodsToSkipCompilation, 0, profile1, &info1);
205   ProfileCompilationInfo info2;
206   SetupProfile("p2", 2, kNumberOfMethodsToSkipCompilation, 0, profile2, &info2);
207 
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 
TEST_F(ProfileAssistantTest,FailProcessingBecauseOfProfiles)231 TEST_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;
244   SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
245   ProfileCompilationInfo info2;
246   SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
247 
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 
TEST_F(ProfileAssistantTest,FailProcessingBecauseOfReferenceProfiles)260 TEST_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;
271   SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
272   ProfileCompilationInfo reference_info;
273   SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, reference_profile, &reference_info);
274 
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
286