blob: ce8233bbea94fbf3d101aa5f3340514a6819892a [file] [log] [blame]
Calin Juravle4d77b6a2015-12-01 18:38:09 +00001/*
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"
Mathieu Chartier06bed302017-07-13 13:23:18 -070022#include "method_reference.h"
Calin Juravle33083d62017-01-18 15:29:12 -080023#include "profile_compilation_info.h"
Calin Juravle138dbff2016-06-28 19:36:58 +010024#include "profile_saver_options.h"
Calin Juravleb4eddd22016-01-13 15:52:33 -080025#include "safe_map.h"
Calin Juravle4d77b6a2015-12-01 18:38:09 +000026
27namespace art {
28
29class ProfileSaver {
30 public:
Calin Juravleb4eddd22016-01-13 15:52:33 -080031 // Starts the profile saver thread if not already started.
32 // If the saver is already running it adds (output_filename, code_paths) to its tracked locations.
Calin Juravle138dbff2016-06-28 19:36:58 +010033 static void Start(const ProfileSaverOptions& options,
34 const std::string& output_filename,
Calin Juravle4d77b6a2015-12-01 18:38:09 +000035 jit::JitCodeCache* jit_code_cache,
Calin Juravle77651c42017-03-03 18:04:02 -080036 const std::vector<std::string>& code_paths)
Calin Juravle4d77b6a2015-12-01 18:38:09 +000037 REQUIRES(!Locks::profiler_lock_, !wait_lock_);
38
39 // Stops the profile saver thread.
40 // NO_THREAD_SAFETY_ANALYSIS for static function calling into member function with excludes lock.
Calin Juravleb8e69992016-03-09 15:37:48 +000041 static void Stop(bool dump_info_)
Calin Juravle4d77b6a2015-12-01 18:38:09 +000042 REQUIRES(!Locks::profiler_lock_, !wait_lock_)
43 NO_THREAD_SAFETY_ANALYSIS;
44
45 // Returns true if the profile saver is started.
46 static bool IsStarted() REQUIRES(!Locks::profiler_lock_);
47
Calin Juravleb8e69992016-03-09 15:37:48 +000048 // If the profile saver is running, dumps statistics to the `os`. Otherwise it does nothing.
49 static void DumpInstanceInfo(std::ostream& os);
50
Calin Juravlea2638922016-04-29 16:44:11 +010051 // NO_THREAD_SAFETY_ANALYSIS for static function calling into member function with excludes lock.
52 static void NotifyJitActivity()
53 REQUIRES(!Locks::profiler_lock_, !wait_lock_)
54 NO_THREAD_SAFETY_ANALYSIS;
55
Mathieu Chartier07ea07e2017-04-05 17:23:54 -070056 // For testing or manual purposes (SIGUSR1).
Calin Juravleffc87072016-04-20 14:22:09 +010057 static void ForceProcessProfiles();
Mathieu Chartier07ea07e2017-04-05 17:23:54 -070058
Mathieu Chartier06bed302017-07-13 13:23:18 -070059 // Just for testing purposes.
60 static bool HasSeenMethod(const std::string& profile, bool hot, MethodReference ref);
Calin Juravleffc87072016-04-20 14:22:09 +010061
Calin Juravle4d77b6a2015-12-01 18:38:09 +000062 private:
Calin Juravle138dbff2016-06-28 19:36:58 +010063 ProfileSaver(const ProfileSaverOptions& options,
64 const std::string& output_filename,
Calin Juravle4d77b6a2015-12-01 18:38:09 +000065 jit::JitCodeCache* jit_code_cache,
Calin Juravle77651c42017-03-03 18:04:02 -080066 const std::vector<std::string>& code_paths);
Calin Juravlecc3171a2017-05-19 16:47:53 -070067 ~ProfileSaver();
Calin Juravle4d77b6a2015-12-01 18:38:09 +000068
69 // NO_THREAD_SAFETY_ANALYSIS for static function calling into member function with excludes lock.
70 static void* RunProfileSaverThread(void* arg)
71 REQUIRES(!Locks::profiler_lock_, !wait_lock_)
72 NO_THREAD_SAFETY_ANALYSIS;
73
74 // The run loop for the saver.
75 void Run() REQUIRES(!Locks::profiler_lock_, !wait_lock_);
Calin Juravlea345d312017-03-14 18:45:55 -070076
Calin Juravle4d77b6a2015-12-01 18:38:09 +000077 // Processes the existing profiling info from the jit code cache and returns
78 // true if it needed to be saved to disk.
Calin Juravlea345d312017-03-14 18:45:55 -070079 // If number_of_new_methods is not null, after the call it will contain the number of new methods
80 // written to disk.
81 // If force_save is true, the saver will ignore any constraints which limit IO (e.g. will write
82 // the profile to disk even if it's just one new method).
83 bool ProcessProfilingInfo(bool force_save, /*out*/uint16_t* number_of_new_methods)
Calin Juravleffc87072016-04-20 14:22:09 +010084 REQUIRES(!Locks::profiler_lock_)
85 REQUIRES(!Locks::mutator_lock_);
86
Calin Juravlea2638922016-04-29 16:44:11 +010087 void NotifyJitActivityInternal() REQUIRES(!wait_lock_);
88 void WakeUpSaver() REQUIRES(wait_lock_);
89
Calin Juravle4d77b6a2015-12-01 18:38:09 +000090 // Returns true if the saver is shutting down (ProfileSaver::Stop() has been called).
91 bool ShuttingDown(Thread* self) REQUIRES(!Locks::profiler_lock_);
92
Calin Juravleb4eddd22016-01-13 15:52:33 -080093 void AddTrackedLocations(const std::string& output_filename,
94 const std::vector<std::string>& code_paths)
95 REQUIRES(Locks::profiler_lock_);
96
Mathieu Chartier27ed3a42016-05-18 08:51:52 -070097 // Fetches the current resolved classes and methods from the ClassLinker and stores them in the
98 // profile_cache_ for later save.
Mathieu Chartier06bed302017-07-13 13:23:18 -070099 void FetchAndCacheResolvedClassesAndMethods(bool startup);
Calin Juravle67265462016-03-18 16:23:40 +0000100
Calin Juravleb8e69992016-03-09 15:37:48 +0000101 void DumpInfo(std::ostream& os);
102
Calin Juravle8b5d9b62017-05-05 17:27:23 -0700103 // Resolve the realpath of the locations stored in tracked_dex_base_locations_to_be_resolved_
104 // and put the result in tracked_dex_base_locations_.
105 void ResolveTrackedLocations() REQUIRES(!Locks::profiler_lock_);
106
Calin Juravle4d77b6a2015-12-01 18:38:09 +0000107 // The only instance of the saver.
108 static ProfileSaver* instance_ GUARDED_BY(Locks::profiler_lock_);
109 // Profile saver thread.
110 static pthread_t profiler_pthread_ GUARDED_BY(Locks::profiler_lock_);
111
Calin Juravle4d77b6a2015-12-01 18:38:09 +0000112 jit::JitCodeCache* jit_code_cache_;
Calin Juravle20b7e3b2016-04-18 18:59:22 +0100113
Calin Juravle8b5d9b62017-05-05 17:27:23 -0700114 // Collection of code paths that the profiler tracks.
Calin Juravle20b7e3b2016-04-18 18:59:22 +0100115 // It maps profile locations to code paths (dex base locations).
Calin Juravleb4eddd22016-01-13 15:52:33 -0800116 SafeMap<std::string, std::set<std::string>> tracked_dex_base_locations_
117 GUARDED_BY(Locks::profiler_lock_);
Calin Juravle20b7e3b2016-04-18 18:59:22 +0100118
Calin Juravle8b5d9b62017-05-05 17:27:23 -0700119 // Collection of code paths that the profiler tracks but may note have been resolved
120 // to their realpath. The resolution is done async to minimize the time it takes for
121 // someone to register a path.
122 SafeMap<std::string, std::set<std::string>> tracked_dex_base_locations_to_be_resolved_
123 GUARDED_BY(Locks::profiler_lock_);
124
Calin Juravle4d77b6a2015-12-01 18:38:09 +0000125 bool shutting_down_ GUARDED_BY(Locks::profiler_lock_);
Calin Juravlea2638922016-04-29 16:44:11 +0100126 uint64_t last_time_ns_saver_woke_up_ GUARDED_BY(wait_lock_);
127 uint32_t jit_activity_notifications_;
Calin Juravle67265462016-03-18 16:23:40 +0000128
129 // A local cache for the profile information. Maps each tracked file to its
Calin Juravledcab1902017-05-12 19:18:47 -0700130 // profile information. This is used to cache the startup classes so that
131 // we don't hammer the disk to save them right away.
132 // The size of this cache is usually very small and tops
Calin Juravle67265462016-03-18 16:23:40 +0000133 // to just a few hundreds entries in the ProfileCompilationInfo objects.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700134 SafeMap<std::string, ProfileCompilationInfo*> profile_cache_;
Calin Juravle4d77b6a2015-12-01 18:38:09 +0000135
136 // Save period condition support.
137 Mutex wait_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
138 ConditionVariable period_condition_ GUARDED_BY(wait_lock_);
139
Calin Juravleb8e69992016-03-09 15:37:48 +0000140 uint64_t total_bytes_written_;
141 uint64_t total_number_of_writes_;
142 uint64_t total_number_of_code_cache_queries_;
143 uint64_t total_number_of_skipped_writes_;
144 uint64_t total_number_of_failed_writes_;
Calin Juravle67265462016-03-18 16:23:40 +0000145 uint64_t total_ms_of_sleep_;
Calin Juravleb8e69992016-03-09 15:37:48 +0000146 uint64_t total_ns_of_work_;
Calin Juravle67265462016-03-18 16:23:40 +0000147 // TODO(calin): replace with an actual size.
148 uint64_t max_number_of_profile_entries_cached_;
Calin Juravlea2638922016-04-29 16:44:11 +0100149 uint64_t total_number_of_hot_spikes_;
150 uint64_t total_number_of_wake_ups_;
Calin Juravleb8e69992016-03-09 15:37:48 +0000151
Calin Juravle138dbff2016-06-28 19:36:58 +0100152 const ProfileSaverOptions options_;
Calin Juravle4d77b6a2015-12-01 18:38:09 +0000153 DISALLOW_COPY_AND_ASSIGN(ProfileSaver);
154};
155
156} // namespace art
157
158#endif // ART_RUNTIME_JIT_PROFILE_SAVER_H_