1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_JIT_PROFILE_SAVER_H_
#define ART_RUNTIME_JIT_PROFILE_SAVER_H_
#include "base/mutex.h"
#include "base/safe_map.h"
#include "dex/method_reference.h"
#include "jit_code_cache.h"
#include "profile/profile_compilation_info.h"
#include "profile_saver_options.h"
namespace art {
class ProfileSaver {
public:
// Starts the profile saver thread if not already started.
// If the saver is already running it adds (output_filename, code_paths) to its tracked locations.
//
// The `ref_profile_filename` denotes the path to the reference profile which
// might be queried to determine if an initial save should be done earlier.
// It can be empty indicating there is no reference profile.
static void Start(const ProfileSaverOptions& options,
const std::string& output_filename,
jit::JitCodeCache* jit_code_cache,
const std::vector<std::string>& code_paths,
const std::string& ref_profile_filename)
REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
// Stops the profile saver thread.
static void Stop(bool dump_info_) REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
// Returns true if the profile saver is started.
static bool IsStarted() REQUIRES(!Locks::profiler_lock_);
// If the profile saver is running, dumps statistics to the `os`. Otherwise it does nothing.
static void DumpInstanceInfo(std::ostream& os);
static void NotifyJitActivity() REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
// For testing or manual purposes (SIGUSR1).
static void ForceProcessProfiles() REQUIRES(!Locks::profiler_lock_, !Locks::mutator_lock_);
// Notify that startup has completed.
static void NotifyStartupCompleted() REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
private:
// Helper classes for collecting classes and methods.
class GetClassesAndMethodsHelper;
class ScopedDefaultPriority;
ProfileSaver(const ProfileSaverOptions& options, jit::JitCodeCache* jit_code_cache);
~ProfileSaver();
static void* RunProfileSaverThread(void* arg)
REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
// The run loop for the saver.
void Run()
REQUIRES(Locks::profiler_lock_, !wait_lock_)
RELEASE(Locks::profiler_lock_);
// Processes the existing profiling info from the jit code cache and returns
// true if it needed to be saved to disk.
// If number_of_new_methods is not null, after the call it will contain the number of new methods
// written to disk.
// If force_save is true, the saver will ignore any constraints which limit IO (e.g. will write
// the profile to disk even if it's just one new method).
bool ProcessProfilingInfo(
bool force_save,
bool skip_class_and_method_fetching,
/*out*/uint16_t* number_of_new_methods)
REQUIRES(!Locks::profiler_lock_)
REQUIRES(!Locks::mutator_lock_);
void NotifyJitActivityInternal() REQUIRES(!wait_lock_);
void WakeUpSaver() REQUIRES(wait_lock_);
// Returns true if the saver is shutting down (ProfileSaver::Stop() has been called).
bool ShuttingDown(Thread* self) REQUIRES(!Locks::profiler_lock_);
void AddTrackedLocations(const std::string& output_filename,
const std::vector<std::string>& code_paths,
const std::string& ref_profile_filename)
REQUIRES(Locks::profiler_lock_);
// Fetches the current resolved classes and methods from the ClassLinker and stores them in the
// profile_cache_ for later save.
void FetchAndCacheResolvedClassesAndMethods(bool startup) REQUIRES(!Locks::profiler_lock_);
void DumpInfo(std::ostream& os);
// Resolve the realpath of the locations stored in tracked_dex_base_locations_to_be_resolved_
// and put the result in tracked_dex_base_locations_.
void ResolveTrackedLocations() REQUIRES(!Locks::profiler_lock_);
// Get the profile metadata that should be associated with the profile session during the current
// profile saver session.
ProfileCompilationInfo::ProfileSampleAnnotation GetProfileSampleAnnotation();
// Get extra global flags if necessary (e.g. the running architecture), otherwise 0.
static uint32_t GetExtraMethodHotnessFlags(const ProfileSaverOptions& options);
// Extends the given set of flags with global flags if necessary (e.g. the running architecture).
ProfileCompilationInfo::MethodHotness::Flag AnnotateSampleFlags(uint32_t flags);
// The only instance of the saver.
static ProfileSaver* instance_ GUARDED_BY(Locks::profiler_lock_);
// Profile saver thread.
static pthread_t profiler_pthread_ GUARDED_BY(Locks::profiler_lock_);
jit::JitCodeCache* jit_code_cache_;
// Collection of code paths that the profiler tracks.
// It maps profile locations to code paths (dex base locations).
SafeMap<std::string, std::set<std::string>> tracked_dex_base_locations_
GUARDED_BY(Locks::profiler_lock_);
// Collection of code paths that the profiler tracks but may note have been resolved
// to their realpath. The resolution is done async to minimize the time it takes for
// someone to register a path.
SafeMap<std::string, std::set<std::string>> tracked_dex_base_locations_to_be_resolved_
GUARDED_BY(Locks::profiler_lock_);
// Collection of output profiles that the profile tracks.
// It maps output profile locations to reference profiles, and is used
// to determine if any profile is non-empty at the start of the ProfileSaver.
// This influences the time of the first ever save.
SafeMap<std::string, std::string> tracked_profiles_
GUARDED_BY(Locks::profiler_lock_);
bool shutting_down_ GUARDED_BY(Locks::profiler_lock_);
uint64_t last_time_ns_saver_woke_up_ GUARDED_BY(wait_lock_);
uint32_t jit_activity_notifications_;
// A local cache for the profile information. Maps each tracked file to its
// profile information. This is used to cache the startup classes so that
// we don't hammer the disk to save them right away.
// The size of this cache is usually very small and tops
// to just a few hundreds entries in the ProfileCompilationInfo objects.
SafeMap<std::string, ProfileCompilationInfo*> profile_cache_ GUARDED_BY(Locks::profiler_lock_);
// Whether or not this is the first ever profile save.
// Note this is an approximation and is not 100% precise. It relies on checking
// whether or not the profiles are empty which is not a precise indication
// of being the first save (they could have been cleared in the meantime).
bool IsFirstSave() REQUIRES(!Locks::profiler_lock_);
// Save period condition support.
Mutex wait_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
ConditionVariable period_condition_ GUARDED_BY(wait_lock_);
uint64_t total_bytes_written_;
uint64_t total_number_of_writes_;
uint64_t total_number_of_code_cache_queries_;
uint64_t total_number_of_skipped_writes_;
uint64_t total_number_of_failed_writes_;
uint64_t total_ms_of_sleep_;
uint64_t total_ns_of_work_;
// TODO(calin): replace with an actual size.
uint64_t total_number_of_hot_spikes_;
uint64_t total_number_of_wake_ups_;
const ProfileSaverOptions options_;
friend class ProfileSaverTest;
friend class ProfileSaverForBootTest;
DISALLOW_COPY_AND_ASSIGN(ProfileSaver);
};
} // namespace art
#endif // ART_RUNTIME_JIT_PROFILE_SAVER_H_
|