1 /* 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 #ifndef ART_RUNTIME_JIT_PROFILE_SAVER_H_ 18 #define ART_RUNTIME_JIT_PROFILE_SAVER_H_ 19 20 #include "base/mutex.h" 21 #include "jit_code_cache.h" 22 #include "offline_profiling_info.h" 23 #include "safe_map.h" 24 25 namespace art { 26 27 class ProfileSaver { 28 public: 29 // Starts the profile saver thread if not already started. 30 // If the saver is already running it adds (output_filename, code_paths) to its tracked locations. 31 static void Start(const std::string& output_filename, 32 jit::JitCodeCache* jit_code_cache, 33 const std::vector<std::string>& code_paths, 34 const std::string& foreign_dex_profile_path, 35 const std::string& app_data_dir) 36 REQUIRES(!Locks::profiler_lock_, !wait_lock_); 37 38 // Stops the profile saver thread. 39 // NO_THREAD_SAFETY_ANALYSIS for static function calling into member function with excludes lock. 40 static void Stop(bool dump_info_) 41 REQUIRES(!Locks::profiler_lock_, !wait_lock_) 42 NO_THREAD_SAFETY_ANALYSIS; 43 44 // Returns true if the profile saver is started. 45 static bool IsStarted() REQUIRES(!Locks::profiler_lock_); 46 47 static void NotifyDexUse(const std::string& dex_location); 48 49 // If the profile saver is running, dumps statistics to the `os`. Otherwise it does nothing. 50 static void DumpInstanceInfo(std::ostream& os); 51 52 // NO_THREAD_SAFETY_ANALYSIS for static function calling into member function with excludes lock. 53 static void NotifyJitActivity() 54 REQUIRES(!Locks::profiler_lock_, !wait_lock_) 55 NO_THREAD_SAFETY_ANALYSIS; 56 57 // Just for testing purpose. 58 static void ForceProcessProfiles(); 59 static bool HasSeenMethod(const std::string& profile, 60 const DexFile* dex_file, 61 uint16_t method_idx); 62 63 private: 64 ProfileSaver(const std::string& output_filename, 65 jit::JitCodeCache* jit_code_cache, 66 const std::vector<std::string>& code_paths, 67 const std::string& foreign_dex_profile_path, 68 const std::string& app_data_dir); 69 70 // NO_THREAD_SAFETY_ANALYSIS for static function calling into member function with excludes lock. 71 static void* RunProfileSaverThread(void* arg) 72 REQUIRES(!Locks::profiler_lock_, !wait_lock_) 73 NO_THREAD_SAFETY_ANALYSIS; 74 75 // The run loop for the saver. 76 void Run() REQUIRES(!Locks::profiler_lock_, !wait_lock_); 77 // Processes the existing profiling info from the jit code cache and returns 78 // true if it needed to be saved to disk. 79 bool ProcessProfilingInfo(uint16_t* new_methods) 80 REQUIRES(!Locks::profiler_lock_) 81 REQUIRES(!Locks::mutator_lock_); 82 83 void NotifyJitActivityInternal() REQUIRES(!wait_lock_); 84 void WakeUpSaver() REQUIRES(wait_lock_); 85 86 // Returns true if the saver is shutting down (ProfileSaver::Stop() has been called). 87 bool ShuttingDown(Thread* self) REQUIRES(!Locks::profiler_lock_); 88 89 void AddTrackedLocations(const std::string& output_filename, 90 const std::string& app_data_dir, 91 const std::vector<std::string>& code_paths) 92 REQUIRES(Locks::profiler_lock_); 93 94 // Retrieves the cached profile compilation info for the given profile file. 95 // If no entry exists, a new empty one will be created, added to the cache and 96 // then returned. 97 ProfileCompilationInfo* GetCachedProfiledInfo(const std::string& filename); 98 // Fetches the current resolved classes and methods from the ClassLinker and stores them in the 99 // profile_cache_ for later save. 100 void FetchAndCacheResolvedClassesAndMethods(); 101 102 static bool MaybeRecordDexUseInternal( 103 const std::string& dex_location, 104 const std::set<std::string>& tracked_locations, 105 const std::string& foreign_dex_profile_path, 106 const std::set<std::string>& app_data_dirs); 107 108 void DumpInfo(std::ostream& os); 109 110 // The only instance of the saver. 111 static ProfileSaver* instance_ GUARDED_BY(Locks::profiler_lock_); 112 // Profile saver thread. 113 static pthread_t profiler_pthread_ GUARDED_BY(Locks::profiler_lock_); 114 115 jit::JitCodeCache* jit_code_cache_; 116 117 // Collection of code paths that the profiles tracks. 118 // It maps profile locations to code paths (dex base locations). 119 SafeMap<std::string, std::set<std::string>> tracked_dex_base_locations_ 120 GUARDED_BY(Locks::profiler_lock_); 121 // The directory were the we should store the code paths. 122 std::string foreign_dex_profile_path_; 123 124 // A list of application directories, used to infer if a loaded dex belongs 125 // to the application or not. Multiple application data directories are possible when 126 // different apps share the same runtime. 127 std::set<std::string> app_data_dirs_ GUARDED_BY(Locks::profiler_lock_); 128 129 bool shutting_down_ GUARDED_BY(Locks::profiler_lock_); 130 uint32_t last_save_number_of_methods_; 131 uint32_t last_save_number_of_classes_; 132 uint64_t last_time_ns_saver_woke_up_ GUARDED_BY(wait_lock_); 133 uint32_t jit_activity_notifications_; 134 135 // A local cache for the profile information. Maps each tracked file to its 136 // profile information. The size of this cache is usually very small and tops 137 // to just a few hundreds entries in the ProfileCompilationInfo objects. 138 // It helps avoiding unnecessary writes to disk. 139 SafeMap<std::string, ProfileCompilationInfo> profile_cache_; 140 141 // Save period condition support. 142 Mutex wait_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 143 ConditionVariable period_condition_ GUARDED_BY(wait_lock_); 144 145 uint64_t total_bytes_written_; 146 uint64_t total_number_of_writes_; 147 uint64_t total_number_of_code_cache_queries_; 148 uint64_t total_number_of_skipped_writes_; 149 uint64_t total_number_of_failed_writes_; 150 uint64_t total_ms_of_sleep_; 151 uint64_t total_ns_of_work_; 152 uint64_t total_number_of_foreign_dex_marks_; 153 // TODO(calin): replace with an actual size. 154 uint64_t max_number_of_profile_entries_cached_; 155 uint64_t total_number_of_hot_spikes_; 156 uint64_t total_number_of_wake_ups_; 157 158 DISALLOW_COPY_AND_ASSIGN(ProfileSaver); 159 }; 160 161 } // namespace art 162 163 #endif // ART_RUNTIME_JIT_PROFILE_SAVER_H_ 164