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 #ifndef ART_PROFMAN_PROFILE_ASSISTANT_H_
18 #define ART_PROFMAN_PROFILE_ASSISTANT_H_
19 
20 #include <string>
21 #include <vector>
22 
23 #include "base/scoped_flock.h"
24 #include "profile/profile_compilation_info.h"
25 
26 namespace art {
27 
28 class ProfileAssistant {
29  public:
30   // These also serve as return codes of profman and are processed by installd
31   // (frameworks/native/cmds/installd/commands.cpp)
32   enum ProcessingResult {
33     kSuccess = 0,  // Generic success code for non-analysis runs.
34     kCompile = 1,
35     kSkipCompilationSmallDelta = 2,
36     kErrorBadProfiles = 3,
37     kErrorIO = 4,
38     kErrorCannotLock = 5,
39     kErrorDifferentVersions = 6,
40     kSkipCompilationEmptyProfiles = 7,
41   };
42 
43   class Options {
44    public:
45     static constexpr bool kForceMergeDefault = false;
46     static constexpr bool kBootImageMergeDefault = false;
47     static constexpr uint32_t kMinNewMethodsPercentChangeForCompilation = 20;
48     static constexpr uint32_t kMinNewClassesPercentChangeForCompilation = 20;
49 
Options()50     Options()
51         : force_merge_(kForceMergeDefault),
52           boot_image_merge_(kBootImageMergeDefault),
53           min_new_methods_percent_change_for_compilation_(
54               kMinNewMethodsPercentChangeForCompilation),
55           min_new_classes_percent_change_for_compilation_(
56               kMinNewClassesPercentChangeForCompilation) {
57     }
58 
IsForceMerge()59     bool IsForceMerge() const { return force_merge_; }
IsBootImageMerge()60     bool IsBootImageMerge() const { return boot_image_merge_; }
GetMinNewMethodsPercentChangeForCompilation()61     uint32_t GetMinNewMethodsPercentChangeForCompilation() const {
62         return min_new_methods_percent_change_for_compilation_;
63     }
GetMinNewClassesPercentChangeForCompilation()64     uint32_t GetMinNewClassesPercentChangeForCompilation() const {
65         return min_new_classes_percent_change_for_compilation_;
66     }
67 
SetForceMerge(bool value)68     void SetForceMerge(bool value) { force_merge_ = value; }
SetBootImageMerge(bool value)69     void SetBootImageMerge(bool value) { boot_image_merge_ = value; }
SetMinNewMethodsPercentChangeForCompilation(uint32_t value)70     void SetMinNewMethodsPercentChangeForCompilation(uint32_t value) {
71       min_new_methods_percent_change_for_compilation_ = value;
72     }
SetMinNewClassesPercentChangeForCompilation(uint32_t value)73     void SetMinNewClassesPercentChangeForCompilation(uint32_t value) {
74       min_new_classes_percent_change_for_compilation_ = value;
75     }
76 
77    private:
78     // If true, performs a forced merge, without analyzing if there is a
79     // significant difference between the current profile and the reference profile.
80     // See ProfileAssistant#ProcessProfile.
81     bool force_merge_;
82     // Signals that the merge is for boot image profiles. It will ignore differences
83     // in profile versions (instead of aborting).
84     bool boot_image_merge_;
85     uint32_t min_new_methods_percent_change_for_compilation_;
86     uint32_t min_new_classes_percent_change_for_compilation_;
87   };
88 
89   // Process the profile information present in the given files. Returns one of
90   // ProcessingResult values depending on profile information and whether or not
91   // the analysis ended up successfully (i.e. no errors during reading,
92   // merging or writing of profile files).
93   //
94   // When the returned value is kCompile there is a significant difference
95   // between profile_files and reference_profile_files. In this case
96   // reference_profile will be updated with the profiling info obtain after
97   // merging all profiles.
98   //
99   // When the returned value is kSkipCompilationSmallDelta, the difference between
100   // the merge of the current profiles and the reference one is insignificant. In
101   // this case no file will be updated. A variation of this code is
102   // kSkipCompilationEmptyProfiles which indicates that all the profiles are empty.
103   // This allow the caller to make fine grain decisions on the compilation strategy.
104   static ProcessingResult ProcessProfiles(
105       const std::vector<std::string>& profile_files,
106       const std::string& reference_profile_file,
107       const ProfileCompilationInfo::ProfileLoadFilterFn& filter_fn
108           = ProfileCompilationInfo::ProfileFilterFnAcceptAll,
109       const Options& options = Options());
110 
111   static ProcessingResult ProcessProfiles(
112       const std::vector<int>& profile_files_fd_,
113       int reference_profile_file_fd,
114       const ProfileCompilationInfo::ProfileLoadFilterFn& filter_fn
115           = ProfileCompilationInfo::ProfileFilterFnAcceptAll,
116       const Options& options = Options());
117 
118  private:
119   static ProcessingResult ProcessProfilesInternal(
120       const std::vector<ScopedFlock>& profile_files,
121       const ScopedFlock& reference_profile_file,
122       const ProfileCompilationInfo::ProfileLoadFilterFn& filter_fn,
123       const Options& options);
124 
125   DISALLOW_COPY_AND_ASSIGN(ProfileAssistant);
126 };
127 
128 }  // namespace art
129 
130 #endif  // ART_PROFMAN_PROFILE_ASSISTANT_H_
131