diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 6 | ||||
-rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 12 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 33 | ||||
-rw-r--r-- | runtime/parsed_options.h | 7 | ||||
-rw-r--r-- | runtime/profiler.cc | 74 | ||||
-rw-r--r-- | runtime/profiler.h | 62 | ||||
-rw-r--r-- | runtime/profiler_options.h | 131 | ||||
-rw-r--r-- | runtime/runtime.cc | 33 | ||||
-rw-r--r-- | runtime/runtime.h | 17 | ||||
-rw-r--r-- | runtime/utils.cc | 19 | ||||
-rw-r--r-- | runtime/utils.h | 4 |
11 files changed, 229 insertions, 169 deletions
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 6085722..2c24e33 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -328,7 +328,7 @@ static jboolean IsDexOptNeededInternal(JNIEnv* env, const char* filename, // If the 'defer' argument is true then this will be retried later. In this case we // need to make sure that the profile file copy is not made so that we will get the // same result second time. - if (pkgname != nullptr) { + if (Runtime::Current()->GetProfilerOptions().IsEnabled() && (pkgname != nullptr)) { const std::string profile_file = GetDalvikCacheOrDie("profiles", false /* create_if_absent */) + std::string("/") + pkgname; const std::string profile_cache_dir = GetDalvikCacheOrDie("profile-cache", @@ -357,8 +357,8 @@ static jboolean IsDexOptNeededInternal(JNIEnv* env, const char* filename, // There is a previous profile file. Check if the profile has changed significantly. // A change in profile is considered significant if X% (change_thr property) of the top K% // (compile_thr property) samples has changed. - double top_k_threshold = GetDoubleProperty("dalvik.vm.profiler.dex2oat.compile_thr", 10.0, 90.0, 90.0); - double change_threshold = GetDoubleProperty("dalvik.vm.profiler.dex2oat.change_thr", 1.0, 90.0, 10.0); + double top_k_threshold = Runtime::Current()->GetProfilerOptions().GetTopKThreshold(); + double change_threshold = Runtime::Current()->GetProfilerOptions().GetTopKChangeThreshold(); double change_percent = 0.0; ProfileFile new_profile, old_profile; bool new_ok = new_profile.LoadFile(profile_file); diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index a369365..f1a987f 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -509,15 +509,13 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) { * process name. We use this information to start up the sampling profiler for * for ART. */ -static void VMRuntime_registerAppInfo(JNIEnv* env, jclass, jstring pkgName, jstring appDir, jstring procName) { +static void VMRuntime_registerAppInfo(JNIEnv* env, jclass, jstring pkgName, + jstring appDir, jstring procName) { const char *pkgNameChars = env->GetStringUTFChars(pkgName, NULL); - const char *appDirChars = env->GetStringUTFChars(appDir, NULL); - const char *procNameChars = env->GetStringUTFChars(procName, NULL); - std::string profileFile = StringPrintf("/data/dalvik-cache/profiles/%s", pkgNameChars); - Runtime::Current()->StartProfiler(profileFile.c_str(), procNameChars); - env->ReleaseStringUTFChars(appDir, appDirChars); - env->ReleaseStringUTFChars(procName, procNameChars); + + Runtime::Current()->StartProfiler(profileFile.c_str()); + env->ReleaseStringUTFChars(pkgName, pkgNameChars); } diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 72a868e..29868e3 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -248,12 +248,6 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni method_trace_file_ = "/data/method-trace-file.bin"; method_trace_file_size_ = 10 * MB; - profile_ = false; - profile_period_s_ = 10; // Seconds. - profile_duration_s_ = 20; // Seconds. - profile_interval_us_ = 500; // Microseconds. - profile_backoff_coefficient_ = 2.0; - profile_start_immediately_ = true; profile_clock_source_ = kDefaultProfilerClockSource; verify_ = true; @@ -534,29 +528,38 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni Trace::SetDefaultClockSource(kProfilerClockSourceWall); } else if (option == "-Xprofile:dualclock") { Trace::SetDefaultClockSource(kProfilerClockSourceDual); + } else if (option == "-Xenable-profiler") { + profiler_options_.enabled_ = true; } else if (StartsWith(option, "-Xprofile-filename:")) { if (!ParseStringAfterChar(option, ':', &profile_output_filename_)) { return false; } - profile_ = true; } else if (StartsWith(option, "-Xprofile-period:")) { - if (!ParseUnsignedInteger(option, ':', &profile_period_s_)) { + if (!ParseUnsignedInteger(option, ':', &profiler_options_.period_s_)) { return false; } } else if (StartsWith(option, "-Xprofile-duration:")) { - if (!ParseUnsignedInteger(option, ':', &profile_duration_s_)) { + if (!ParseUnsignedInteger(option, ':', &profiler_options_.duration_s_)) { return false; } } else if (StartsWith(option, "-Xprofile-interval:")) { - if (!ParseUnsignedInteger(option, ':', &profile_interval_us_)) { + if (!ParseUnsignedInteger(option, ':', &profiler_options_.interval_us_)) { return false; } } else if (StartsWith(option, "-Xprofile-backoff:")) { - if (!ParseDouble(option, ':', 1.0, 10.0, &profile_backoff_coefficient_)) { + if (!ParseDouble(option, ':', 1.0, 10.0, &profiler_options_.backoff_coefficient_)) { + return false; + } + } else if (option == "-Xprofile-start-immediately") { + profiler_options_.start_immediately_ = true; + } else if (StartsWith(option, "-Xprofile-top-k-threshold:")) { + if (!ParseDouble(option, ':', 10.0, 90.0, &profiler_options_.top_k_threshold_)) { + return false; + } + } else if (StartsWith(option, "-Xprofile-top-k-change-threshold:")) { + if (!ParseDouble(option, ':', 10.0, 90.0, &profiler_options_.top_k_change_threshold_)) { return false; } - } else if (option == "-Xprofile-start-lazy") { - profile_start_immediately_ = false; } else if (StartsWith(option, "-implicit-checks:")) { std::string checks; if (!ParseStringAfterChar(option, ':', &checks)) { @@ -791,11 +794,15 @@ void ParsedOptions::Usage(const char* fmt, ...) { UsageMessage(stream, " -Xmethod-trace\n"); UsageMessage(stream, " -Xmethod-trace-file:filename"); UsageMessage(stream, " -Xmethod-trace-file-size:integervalue\n"); + UsageMessage(stream, " -Xenable-profiler\n"); UsageMessage(stream, " -Xprofile-filename:filename\n"); UsageMessage(stream, " -Xprofile-period:integervalue\n"); UsageMessage(stream, " -Xprofile-duration:integervalue\n"); UsageMessage(stream, " -Xprofile-interval:integervalue\n"); UsageMessage(stream, " -Xprofile-backoff:doublevalue\n"); + UsageMessage(stream, " -Xprofile-start-immediately\n"); + UsageMessage(stream, " -Xprofile-top-k-threshold:doublevalue\n"); + UsageMessage(stream, " -Xprofile-top-k-change-threshold:doublevalue\n"); UsageMessage(stream, " -Xcompiler:filename\n"); UsageMessage(stream, " -Xcompiler-option dex2oat-option\n"); UsageMessage(stream, " -Ximage-compiler-option dex2oat-option\n"); diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h index 25fc12a..a27eec6 100644 --- a/runtime/parsed_options.h +++ b/runtime/parsed_options.h @@ -77,13 +77,8 @@ class ParsedOptions { std::string compiler_executable_; std::vector<std::string> compiler_options_; std::vector<std::string> image_compiler_options_; - bool profile_; + ProfilerOptions profiler_options_; std::string profile_output_filename_; - uint32_t profile_period_s_; - uint32_t profile_duration_s_; - uint32_t profile_interval_us_; - double profile_backoff_coefficient_; - bool profile_start_immediately_; ProfilerClockSource profile_clock_source_; bool verify_; InstructionSet image_isa_; diff --git a/runtime/profiler.cc b/runtime/profiler.cc index 75db9da..80ce205 100644 --- a/runtime/profiler.cc +++ b/runtime/profiler.cc @@ -53,7 +53,6 @@ BackgroundMethodSamplingProfiler* BackgroundMethodSamplingProfiler::profiler_ = pthread_t BackgroundMethodSamplingProfiler::profiler_pthread_ = 0U; volatile bool BackgroundMethodSamplingProfiler::shutting_down_ = false; - // TODO: this profiler runs regardless of the state of the machine. Maybe we should use the // wakelock or something to modify the run characteristics. This can be done when we // have some performance data after it's been used for a while. @@ -126,6 +125,7 @@ void* BackgroundMethodSamplingProfiler::RunProfilerThread(void* arg) { Thread* self = Thread::Current(); + double backoff = 1.0; while (true) { if (ShuttingDown(self)) { break; @@ -133,13 +133,13 @@ void* BackgroundMethodSamplingProfiler::RunProfilerThread(void* arg) { { // wait until we need to run another profile - uint64_t delay_secs = profiler->period_s_ * profiler->backoff_factor_; + uint64_t delay_secs = profiler->options_.GetPeriodS() * backoff; // Add a startup delay to prevent all the profiles running at once. delay_secs += startup_delay; // Immediate startup for benchmarking? - if (profiler->start_immediately_ && startup_delay > 0) { + if (profiler->options_.GetStartImmediately() && startup_delay > 0) { delay_secs = 0; } @@ -150,10 +150,7 @@ void* BackgroundMethodSamplingProfiler::RunProfilerThread(void* arg) { profiler->period_condition_.TimedWait(self, delay_secs * 1000, 0); // Expand the backoff by its coefficient, but don't go beyond the max. - double new_backoff = profiler->backoff_factor_ * profiler->backoff_coefficient_; - if (new_backoff < kMaxBackoffSecs) { - profiler->backoff_factor_ = new_backoff; - } + backoff = std::min(backoff * profiler->options_.GetBackoffCoefficient(), kMaxBackoffSecs); } if (ShuttingDown(self)) { @@ -162,11 +159,11 @@ void* BackgroundMethodSamplingProfiler::RunProfilerThread(void* arg) { uint64_t start_us = MicroTime(); - uint64_t end_us = start_us + profiler->duration_s_ * UINT64_C(1000000); + uint64_t end_us = start_us + profiler->options_.GetDurationS() * UINT64_C(1000000); uint64_t now_us = start_us; - VLOG(profiler) << "Starting profiling run now for " << PrettyDuration((end_us - start_us) * 1000); - + VLOG(profiler) << "Starting profiling run now for " + << PrettyDuration((end_us - start_us) * 1000); SampleCheckpoint check_point(profiler); @@ -176,7 +173,7 @@ void* BackgroundMethodSamplingProfiler::RunProfilerThread(void* arg) { break; } - usleep(profiler->interval_us_); // Non-interruptible sleep. + usleep(profiler->options_.GetIntervalUs()); // Non-interruptible sleep. ThreadList* thread_list = runtime->GetThreadList(); @@ -228,7 +225,7 @@ void* BackgroundMethodSamplingProfiler::RunProfilerThread(void* arg) { // Write out the profile file if we are generating a profile. uint32_t BackgroundMethodSamplingProfiler::WriteProfile() { - std::string full_name = profile_file_name_; + std::string full_name = output_filename_; VLOG(profiler) << "Saving profile to " << full_name; int fd = open(full_name.c_str(), O_RDWR); @@ -283,45 +280,35 @@ uint32_t BackgroundMethodSamplingProfiler::WriteProfile() { return num_methods; } -// Start a profile thread with the user-supplied arguments. -void BackgroundMethodSamplingProfiler::Start(int period, int duration, - const std::string& profile_file_name, const std::string& procName, - int interval_us, - double backoff_coefficient, bool startImmediately) { +bool BackgroundMethodSamplingProfiler::Start( + const std::string& output_filename, const ProfilerOptions& options) { + if (!options.IsEnabled()) { + LOG(INFO) << "Profiler disabled. To enable setprop dalvik.vm.profiler 1."; + return false; + } + + CHECK(!output_filename.empty()); + Thread* self = Thread::Current(); { MutexLock mu(self, *Locks::profiler_lock_); // Don't start two profiler threads. if (profiler_ != nullptr) { - return; + return true; } } - // Only on target... -#ifdef HAVE_ANDROID_OS - // Switch off profiler if the dalvik.vm.profiler property has value 0. - char buf[PROP_VALUE_MAX]; - property_get("dalvik.vm.profiler", buf, "0"); - if (strcmp(buf, "0") == 0) { - LOG(INFO) << "Profiler disabled. To enable setprop dalvik.vm.profiler 1"; - return; - } -#endif - - LOG(INFO) << "Starting profile with period " << period << "s, duration " << duration << - "s, interval " << interval_us << "us. Profile file " << profile_file_name; - + LOG(INFO) << "Starting profiler using output file: " << output_filename + << " and options: " << options; { MutexLock mu(self, *Locks::profiler_lock_); - profiler_ = new BackgroundMethodSamplingProfiler(period, duration, profile_file_name, - procName, - backoff_coefficient, - interval_us, startImmediately); + profiler_ = new BackgroundMethodSamplingProfiler(output_filename, options); CHECK_PTHREAD_CALL(pthread_create, (&profiler_pthread_, nullptr, &RunProfilerThread, reinterpret_cast<void*>(profiler_)), "Profiler thread"); } + return true; } @@ -357,14 +344,10 @@ void BackgroundMethodSamplingProfiler::Shutdown() { Stop(); } -BackgroundMethodSamplingProfiler::BackgroundMethodSamplingProfiler(int period, int duration, - const std::string& profile_file_name, - const std::string& process_name, - double backoff_coefficient, int interval_us, bool startImmediately) - : profile_file_name_(profile_file_name), process_name_(process_name), - period_s_(period), start_immediately_(startImmediately), - interval_us_(interval_us), backoff_factor_(1.0), - backoff_coefficient_(backoff_coefficient), duration_s_(duration), +BackgroundMethodSamplingProfiler::BackgroundMethodSamplingProfiler( + const std::string& output_filename, const ProfilerOptions& options) + : output_filename_(output_filename), + options_(options), wait_lock_("Profile wait lock"), period_condition_("Profile condition", wait_lock_), profile_table_(wait_lock_), @@ -466,7 +449,8 @@ uint32_t ProfileSampleResults::Write(std::ostream &os) { num_null_methods_ += previous_num_null_methods_; num_boot_methods_ += previous_num_boot_methods_; - VLOG(profiler) << "Profile: " << num_samples_ << "/" << num_null_methods_ << "/" << num_boot_methods_; + VLOG(profiler) << "Profile: " + << num_samples_ << "/" << num_null_methods_ << "/" << num_boot_methods_; os << num_samples_ << "/" << num_null_methods_ << "/" << num_boot_methods_ << "\n"; uint32_t num_methods = 0; for (int i = 0 ; i < kHashSize; i++) { diff --git a/runtime/profiler.h b/runtime/profiler.h index 2502289..0b18dbb 100644 --- a/runtime/profiler.h +++ b/runtime/profiler.h @@ -28,6 +28,7 @@ #include "base/mutex.h" #include "globals.h" #include "instrumentation.h" +#include "profiler_options.h" #include "os.h" #include "safe_map.h" @@ -62,17 +63,18 @@ class ProfileSampleResults { private: uint32_t Hash(mirror::ArtMethod* method); static constexpr int kHashSize = 17; - Mutex& lock_; // Reference to the main profiler lock - we don't need two of them. - uint32_t num_samples_; // Total number of samples taken. - uint32_t num_null_methods_; // Number of samples where can don't know the method. - uint32_t num_boot_methods_; // Number of samples in the boot path. + Mutex& lock_; // Reference to the main profiler lock - we don't need two of them. + uint32_t num_samples_; // Total number of samples taken. + uint32_t num_null_methods_; // Number of samples where can don't know the method. + uint32_t num_boot_methods_; // Number of samples in the boot path. typedef std::map<mirror::ArtMethod*, uint32_t> Map; // Map of method vs its count. Map *table[kHashSize]; struct PreviousValue { PreviousValue() : count_(0), method_size_(0) {} - PreviousValue(uint32_t count, uint32_t method_size) : count_(count), method_size_(method_size) {} + PreviousValue(uint32_t count, uint32_t method_size) + : count_(count), method_size_(method_size) {} uint32_t count_; uint32_t method_size_; }; @@ -101,9 +103,9 @@ class ProfileSampleResults { class BackgroundMethodSamplingProfiler { public: - static void Start(int period, int duration, const std::string& profile_filename, - const std::string& procName, int interval_us, - double backoff_coefficient, bool startImmediately) + // Start a profile thread with the user-supplied arguments. + // Returns true if the profile was started or if it was already running. Returns false otherwise. + static bool Start(const std::string& output_filename, const ProfilerOptions& options) LOCKS_EXCLUDED(Locks::mutator_lock_, Locks::thread_list_lock_, Locks::thread_suspend_count_lock_, @@ -119,10 +121,8 @@ class BackgroundMethodSamplingProfiler { } private: - explicit BackgroundMethodSamplingProfiler(int period, int duration, - const std::string& profile_filename, - const std::string& process_name, - double backoff_coefficient, int interval_us, bool startImmediately); + explicit BackgroundMethodSamplingProfiler( + const std::string& output_filename, const ProfilerOptions& options); // The sampling interval in microseconds is passed as an argument. static void* RunProfilerThread(void* arg) LOCKS_EXCLUDED(Locks::profiler_lock_); @@ -141,35 +141,14 @@ class BackgroundMethodSamplingProfiler { // Sampling thread, non-zero when sampling. static pthread_t profiler_pthread_; - // Some measure of the number of samples that are significant + // Some measure of the number of samples that are significant. static constexpr uint32_t kSignificantSamples = 10; - // File to write profile data out to. Cannot be empty if we are profiling. - std::string profile_file_name_; + // The name of the file where profile data will be written. + std::string output_filename_; + // The options used to start the profiler. + const ProfilerOptions& options_; - // Process name. - std::string process_name_; - - // Number of seconds between profile runs. - uint32_t period_s_; - - // Most of the time we want to delay the profiler startup to prevent everything - // running at the same time (all processes). This is the default, but if we - // want to override this, set the 'start_immediately_' to true. This is done - // if the -Xprofile option is given on the command line. - bool start_immediately_; - - uint32_t interval_us_; - - // A backoff coefficent to adjust the profile period based on time. - double backoff_factor_; - - // How much to increase the backoff by on each profile iteration. - double backoff_coefficient_; - - // Duration of each profile run. The profile file will be written at the end - // of each run. - uint32_t duration_s_; // Profile condition support. Mutex wait_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; @@ -188,6 +167,7 @@ class BackgroundMethodSamplingProfiler { DISALLOW_COPY_AND_ASSIGN(BackgroundMethodSamplingProfiler); }; +// // Contains profile data generated from previous runs of the program and stored // in a file. It is used to determine whether to compile a particular method or not. class ProfileFile { @@ -212,12 +192,12 @@ class ProfileFile { uint32_t count_; // Number of times it has been called. uint32_t method_size_; // Size of the method on dex instructions. double used_percent_; // Percentage of how many times this method was called. - double top_k_used_percentage_; // The percentage of the group that comprise K% of the total used - // methods this methods belongs to. + double top_k_used_percentage_; // The percentage of the group that comprise K% of the total + // used methods this methods belongs to. }; public: - // Loads profile data from the given file. The data are merged with any existing data. + // Loads profile data from the given file. The new data are merged with any existing data. // Returns true if the file was loaded successfully and false otherwise. bool LoadFile(const std::string& filename); diff --git a/runtime/profiler_options.h b/runtime/profiler_options.h new file mode 100644 index 0000000..08e32cc --- /dev/null +++ b/runtime/profiler_options.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014 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_PROFILER_OPTIONS_H_ +#define ART_RUNTIME_PROFILER_OPTIONS_H_ + +#include <string> +#include <ostream> + +namespace art { + +class ProfilerOptions { + public: + static constexpr bool kDefaultEnabled = false; + static constexpr uint32_t kDefaultPeriodS = 10; + static constexpr uint32_t kDefaultDurationS = 20; + static constexpr uint32_t kDefaultIntervalUs = 500; + static constexpr double kDefaultBackoffCoefficient = 2.0; + static constexpr bool kDefaultStartImmediately = false; + static constexpr double kDefaultTopKThreshold = 90.0; + static constexpr double kDefaultChangeInTopKThreshold = 10.0; + + ProfilerOptions() : + enabled_(kDefaultEnabled), + period_s_(kDefaultPeriodS), + duration_s_(kDefaultDurationS), + interval_us_(kDefaultIntervalUs), + backoff_coefficient_(kDefaultBackoffCoefficient), + start_immediately_(kDefaultStartImmediately), + top_k_threshold_(kDefaultTopKThreshold), + top_k_change_threshold_(kDefaultChangeInTopKThreshold) {} + + ProfilerOptions(bool enabled, + uint32_t period_s, + uint32_t duration_s, + uint32_t interval_us, + double backoff_coefficient, + bool start_immediately, + double top_k_threshold, + double top_k_change_threshold): + enabled_(enabled), + period_s_(period_s), + duration_s_(duration_s), + interval_us_(interval_us), + backoff_coefficient_(backoff_coefficient), + start_immediately_(start_immediately), + top_k_threshold_(top_k_threshold), + top_k_change_threshold_(top_k_change_threshold) {} + + bool IsEnabled() const { + return enabled_; + } + + uint32_t GetPeriodS() const { + return period_s_; + } + + uint32_t GetDurationS() const { + return duration_s_; + } + + uint32_t GetIntervalUs() const { + return interval_us_; + } + + double GetBackoffCoefficient() const { + return backoff_coefficient_; + } + + bool GetStartImmediately() const { + return start_immediately_; + } + + double GetTopKThreshold() const { + return top_k_threshold_; + } + + double GetTopKChangeThreshold() const { + return top_k_change_threshold_; + } + + private: + friend std::ostream & operator<<(std::ostream &os, const ProfilerOptions& po) { + os << "enabled=" << po.enabled_ + << ", period_s=" << po.period_s_ + << ", duration_s=" << po.duration_s_ + << ", interval_us=" << po.interval_us_ + << ", backoff_coefficient=" << po.backoff_coefficient_ + << ", start_immediately=" << po.start_immediately_ + << ", top_k_threshold=" << po.top_k_threshold_ + << ", top_k_change_threshold=" << po.top_k_change_threshold_; + return os; + } + + friend class ParsedOptions; + + // Whether or not the applications should be profiled. + bool enabled_; + // Generate profile every n seconds. + uint32_t period_s_; + // Run profile for n seconds. + uint32_t duration_s_; + // Microseconds between samples. + uint32_t interval_us_; + // Coefficient to exponential backoff. + double backoff_coefficient_; + // Whether the profile should start upon app startup or be delayed by some random offset. + bool start_immediately_; + // Top K% of samples that are considered relevant when deciding if the app should be recompiled. + double top_k_threshold_; + // How much the top K% samples needs to change in order for the app to be recompiled. + double top_k_change_threshold_; +}; + +} // namespace art + + +#endif // ART_RUNTIME_PROFILER_OPTIONS_H_ diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 68b10cc..f16eddf 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -123,12 +123,7 @@ Runtime::Runtime() abort_(nullptr), stats_enabled_(false), running_on_valgrind_(RUNNING_ON_VALGRIND > 0), - profile_(false), - profile_period_s_(0), - profile_duration_s_(0), - profile_interval_us_(0), - profile_backoff_coefficient_(0), - profile_start_immediately_(true), + profiler_started_(false), method_trace_(false), method_trace_file_size_(0), instrumentation_(), @@ -166,7 +161,7 @@ Runtime::~Runtime() { shutting_down_ = true; } // Shut down background profiler before the runtime exits. - if (profile_) { + if (profiler_started_) { BackgroundMethodSamplingProfiler::Shutdown(); } @@ -416,17 +411,16 @@ bool Runtime::Start() { } VLOG(startup) << "Runtime::Start exiting"; - finished_starting_ = true; - if (profile_) { - // User has asked for a profile using -Xprofile + if (profiler_options_.IsEnabled() && !profile_output_filename_.empty()) { + // User has asked for a profile using -Xenable-profiler. // Create the profile file if it doesn't exist. int fd = open(profile_output_filename_.c_str(), O_RDWR|O_CREAT|O_EXCL, 0660); if (fd >= 0) { close(fd); } - StartProfiler(profile_output_filename_.c_str(), ""); + StartProfiler(profile_output_filename_.c_str()); } return true; @@ -664,15 +658,9 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { method_trace_file_ = options->method_trace_file_; method_trace_file_size_ = options->method_trace_file_size_; - // Extract the profile options. - // TODO: move into a Trace options struct? - profile_period_s_ = options->profile_period_s_; - profile_duration_s_ = options->profile_duration_s_; - profile_interval_us_ = options->profile_interval_us_; - profile_backoff_coefficient_ = options->profile_backoff_coefficient_; - profile_start_immediately_ = options->profile_start_immediately_; - profile_ = options->profile_; profile_output_filename_ = options->profile_output_filename_; + profiler_options_ = options->profiler_options_; + // TODO: move this to just be an Trace::Start argument Trace::SetDefaultClockSource(options->profile_clock_source_); @@ -1125,9 +1113,10 @@ void Runtime::RemoveMethodVerifier(verifier::MethodVerifier* verifier) { method_verifiers_.erase(it); } -void Runtime::StartProfiler(const char* appDir, const char* procName) { - BackgroundMethodSamplingProfiler::Start(profile_period_s_, profile_duration_s_, appDir, - procName, profile_interval_us_, profile_backoff_coefficient_, profile_start_immediately_); +void Runtime::StartProfiler(const char* profile_output_filename) { + profile_output_filename_ = profile_output_filename; + profiler_started_ = + BackgroundMethodSamplingProfiler::Start(profile_output_filename_, profiler_options_); } // Transaction support. diff --git a/runtime/runtime.h b/runtime/runtime.h index afb5aa7..808d706 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -34,6 +34,7 @@ #include "instrumentation.h" #include "jobject_comparator.h" #include "object_callbacks.h" +#include "profiler_options.h" #include "quick/quick_method_frame_info.h" #include "runtime_stats.h" #include "safe_map.h" @@ -114,6 +115,10 @@ class Runtime { return image_compiler_options_; } + const ProfilerOptions& GetProfilerOptions() const { + return profiler_options_; + } + // Starts a runtime, which may cause threads to be started and code to run. bool Start() UNLOCK_FUNCTION(Locks::mutator_lock_); @@ -386,7 +391,7 @@ class Runtime { const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader); void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path); - void StartProfiler(const char* appDir, const char* procName); + void StartProfiler(const char* profile_output_filename); void UpdateProfilerState(int state); // Transaction support. @@ -559,15 +564,9 @@ class Runtime { const bool running_on_valgrind_; - // Runtime profile support. - bool profile_; std::string profile_output_filename_; - uint32_t profile_period_s_; // Generate profile every n seconds. - uint32_t profile_duration_s_; // Run profile for n seconds. - uint32_t profile_interval_us_; // Microseconds between samples. - double profile_backoff_coefficient_; // Coefficient to exponential backoff. - bool profile_start_immediately_; // Whether the profile should start upon app - // startup or be delayed by some random offset. + ProfilerOptions profiler_options_; + bool profiler_started_; bool method_trace_; std::string method_trace_file_; diff --git a/runtime/utils.cc b/runtime/utils.cc index 05ff5ff..f562252 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -1302,23 +1302,4 @@ bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) { return true; } -double GetDoubleProperty(const char* property, double min_value, double max_value, double default_value) { -#ifndef HAVE_ANDROID_OS - return default_value; -#else - char buf[PROP_VALUE_MAX]; - char* endptr; - - property_get(property, buf, ""); - double value = strtod(buf, &endptr); - - // Return the defalt value if the string is invalid or the value is outside the given range - if ((value == 0 && endptr == buf) // Invalid string - || (value < min_value) || (value > max_value)) { // Out of range value - return default_value; - } - return value; -#endif -} - } // namespace art diff --git a/runtime/utils.h b/runtime/utils.h index 0f9b22b..7be5d44 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -443,10 +443,6 @@ class VoidFunctor { } }; -// Returns the given property as a double or its default_value if the property string is not valid -// or the parsed value is outside the interval [min_value, max_value]. -double GetDoubleProperty(const char* property, double min_value, double max_value, double default_value); - } // namespace art #endif // ART_RUNTIME_UTILS_H_ |