blob: 08717224404e273f52c52766fb3ba9cbf8f17d02 [file] [log] [blame]
Calin Juravle998c2162015-12-21 15:39:33 +02001/*
2 * Copyright (C) 2015 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 "profile_assistant.h"
18
Calin Juravle877fd962016-01-05 14:29:29 +000019#include "base/unix_file/fd_file.h"
20#include "os.h"
21
Calin Juravle998c2162015-12-21 15:39:33 +020022namespace art {
23
24// Minimum number of new methods that profiles must contain to enable recompilation.
25static constexpr const uint32_t kMinNewMethodsForCompilation = 10;
26
Calin Juravle877fd962016-01-05 14:29:29 +000027bool ProfileAssistant::ProcessProfilesInternal(
28 const std::vector<ScopedFlock>& profile_files,
29 const std::vector<ScopedFlock>& reference_profile_files,
30 /*out*/ ProfileCompilationInfo** profile_compilation_info) {
Calin Juravle998c2162015-12-21 15:39:33 +020031 DCHECK(!profile_files.empty());
Calin Juravle877fd962016-01-05 14:29:29 +000032 DCHECK(!reference_profile_files.empty() ||
Calin Juravle998c2162015-12-21 15:39:33 +020033 (profile_files.size() == reference_profile_files.size()));
Calin Juravle998c2162015-12-21 15:39:33 +020034 std::vector<ProfileCompilationInfo> new_info(profile_files.size());
35 bool should_compile = false;
36 // Read the main profile files.
Calin Juravle877fd962016-01-05 14:29:29 +000037 for (size_t i = 0; i < new_info.size(); i++) {
38 if (!new_info[i].Load(profile_files[i].GetFile()->Fd())) {
39 LOG(WARNING) << "Could not load profile file at index " << i;
Calin Juravle998c2162015-12-21 15:39:33 +020040 return false;
41 }
42 // Do we have enough new profiled methods that will make the compilation worthwhile?
43 should_compile |= (new_info[i].GetNumberOfMethods() > kMinNewMethodsForCompilation);
44 }
Calin Juravle877fd962016-01-05 14:29:29 +000045
Calin Juravle998c2162015-12-21 15:39:33 +020046 if (!should_compile) {
47 *profile_compilation_info = nullptr;
48 return true;
49 }
50
51 std::unique_ptr<ProfileCompilationInfo> result(new ProfileCompilationInfo());
Calin Juravle877fd962016-01-05 14:29:29 +000052 // Merge information.
Calin Juravle998c2162015-12-21 15:39:33 +020053 for (size_t i = 0; i < new_info.size(); i++) {
Calin Juravle998c2162015-12-21 15:39:33 +020054 if (!reference_profile_files.empty()) {
Calin Juravle877fd962016-01-05 14:29:29 +000055 if (!new_info[i].Load(reference_profile_files[i].GetFile()->Fd())) {
56 LOG(WARNING) << "Could not load reference profile file at index " << i;
Calin Juravle998c2162015-12-21 15:39:33 +020057 return false;
58 }
Calin Juravle877fd962016-01-05 14:29:29 +000059 }
60 // Merge all data into a single object.
61 if (!result->Load(new_info[i])) {
62 LOG(WARNING) << "Could not merge profile data at index " << i;
63 return false;
64 }
65 }
66 // We were successful in merging all profile information. Update the files.
67 for (size_t i = 0; i < new_info.size(); i++) {
68 if (!reference_profile_files.empty()) {
69 if (!reference_profile_files[i].GetFile()->ClearContent()) {
70 PLOG(WARNING) << "Could not clear reference profile file at index " << i;
71 return false;
72 }
73 if (!new_info[i].Save(reference_profile_files[i].GetFile()->Fd())) {
74 LOG(WARNING) << "Could not save reference profile file at index " << i;
75 return false;
76 }
77 if (!profile_files[i].GetFile()->ClearContent()) {
78 PLOG(WARNING) << "Could not clear profile file at index " << i;
Calin Juravle998c2162015-12-21 15:39:33 +020079 return false;
80 }
81 }
82 }
Calin Juravle877fd962016-01-05 14:29:29 +000083
Calin Juravle998c2162015-12-21 15:39:33 +020084 *profile_compilation_info = result.release();
85 return true;
86}
87
Calin Juravle877fd962016-01-05 14:29:29 +000088class ScopedCollectionFlock {
89 public:
90 explicit ScopedCollectionFlock(size_t size) : flocks_(size) {}
91
92 // Will block until all the locks are acquired.
93 bool Init(const std::vector<std::string>& filenames, /* out */ std::string* error) {
94 for (size_t i = 0; i < filenames.size(); i++) {
95 if (!flocks_[i].Init(filenames[i].c_str(), O_RDWR, /* block */ true, error)) {
96 *error += " (index=" + std::to_string(i) + ")";
97 return false;
98 }
99 }
100 return true;
101 }
102
103 // Will block until all the locks are acquired.
104 bool Init(const std::vector<uint32_t>& fds, /* out */ std::string* error) {
105 for (size_t i = 0; i < fds.size(); i++) {
106 // We do not own the descriptor, so disable auto-close and don't check usage.
107 File file(fds[i], false);
108 file.DisableAutoClose();
109 if (!flocks_[i].Init(&file, error)) {
110 *error += " (index=" + std::to_string(i) + ")";
111 return false;
112 }
113 }
114 return true;
115 }
116
117 const std::vector<ScopedFlock>& Get() const { return flocks_; }
118
119 private:
120 std::vector<ScopedFlock> flocks_;
121};
122
123bool ProfileAssistant::ProcessProfiles(
124 const std::vector<uint32_t>& profile_files_fd,
125 const std::vector<uint32_t>& reference_profile_files_fd,
126 /*out*/ ProfileCompilationInfo** profile_compilation_info) {
127 std::string error;
128 ScopedCollectionFlock profile_files_flocks(profile_files_fd.size());
129 if (!profile_files_flocks.Init(profile_files_fd, &error)) {
130 LOG(WARNING) << "Could not lock profile files: " << error;
131 return false;
132 }
133 ScopedCollectionFlock reference_profile_files_flocks(reference_profile_files_fd.size());
134 if (!reference_profile_files_flocks.Init(reference_profile_files_fd, &error)) {
135 LOG(WARNING) << "Could not lock reference profile files: " << error;
136 return false;
137 }
138
139 return ProcessProfilesInternal(profile_files_flocks.Get(),
140 reference_profile_files_flocks.Get(),
141 profile_compilation_info);
142}
143
144bool ProfileAssistant::ProcessProfiles(
145 const std::vector<std::string>& profile_files,
146 const std::vector<std::string>& reference_profile_files,
147 /*out*/ ProfileCompilationInfo** profile_compilation_info) {
148 std::string error;
149 ScopedCollectionFlock profile_files_flocks(profile_files.size());
150 if (!profile_files_flocks.Init(profile_files, &error)) {
151 LOG(WARNING) << "Could not lock profile files: " << error;
152 return false;
153 }
154 ScopedCollectionFlock reference_profile_files_flocks(reference_profile_files.size());
155 if (!reference_profile_files_flocks.Init(reference_profile_files, &error)) {
156 LOG(WARNING) << "Could not lock reference profile files: " << error;
157 return false;
158 }
159
160 return ProcessProfilesInternal(profile_files_flocks.Get(),
161 reference_profile_files_flocks.Get(),
162 profile_compilation_info);
163}
164
Calin Juravle998c2162015-12-21 15:39:33 +0200165} // namespace art