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
|
/*
* 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.
static void Start(const ProfileSaverOptions& options,
const std::string& output_filename,
jit::JitCodeCache* jit_code_cache,
const std::vector<std::string>& code_paths)
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_);
// Just for testing purposes.
static bool HasSeenMethod(const std::string& profile, bool hot, MethodReference ref)
REQUIRES(!Locks::profiler_lock_);
// Notify that startup has completed.
static void NotifyStartupCompleted() REQUIRES(!Locks::profiler_lock_, !instance_->wait_lock_);
private:
ProfileSaver(const ProfileSaverOptions& options,
const std::string& output_filename,
jit::JitCodeCache* jit_code_cache,
const std::vector<std::string>& code_paths);
~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, /*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)
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();
// 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_);
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_;
// 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_
|