summaryrefslogtreecommitdiffstats
path: root/compiler/driver/compiler_driver.cc
diff options
context:
space:
mode:
authorDave Allison <dallison@google.com>2014-01-28 18:33:52 -0800
committerDave Allison <dallison@google.com>2014-03-07 13:42:48 -0800
commit39c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13 (patch)
treefa777039b3f7c34f3dd322d04307766246526080 /compiler/driver/compiler_driver.cc
parent0918614b7434783477e8668df7850a7aaf8d5611 (diff)
downloadart-39c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13.zip
art-39c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13.tar.gz
art-39c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13.tar.bz2
Make use of profiling information for dex2oat
If the profile file exists, the compiler driver will read it and store the data in an internal map. Then, when we want to work out whether to compile a method or not, the map is consulted and if the method shows up with a high enough percentage of use we compile it. The profile file itself is created by installd and is writeable by the app. The file is in /data/dalvik-cache/profiles and is named by the package name. This also modifies the profiler itself to: 1. Only count runnable threads (not suspended threads) in the profile 2. Use system properties to allow tuning of the profile parameters 3. Merge profiles from multiple processes using file locking. Bug: 12877748 Change-Id: Iab2f3a327a2860db2a80d5724277d6c626227f2b Conflicts: compiler/dex/frontend.cc compiler/dex/mir_analysis.cc compiler/dex/verification_results.cc compiler/driver/compiler_driver.cc dex2oat/dex2oat.cc runtime/class_linker.cc runtime/runtime.cc runtime/runtime.h
Diffstat (limited to 'compiler/driver/compiler_driver.cc')
-rw-r--r--compiler/driver/compiler_driver.cc94
1 files changed, 91 insertions, 3 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index d3d58c9..a46015d 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -21,6 +21,7 @@
#include <vector>
#include <unistd.h>
+#include <fstream>
#include "base/stl_util.h"
#include "base/timing_logger.h"
@@ -303,8 +304,9 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
InstructionSet instruction_set,
InstructionSetFeatures instruction_set_features,
bool image, DescriptorSet* image_classes, size_t thread_count,
- bool dump_stats, bool dump_passes, CumulativeLogger* timer)
- : compiler_options_(compiler_options),
+ bool dump_stats, bool dump_passes, CumulativeLogger* timer,
+ std::string profile_file)
+ : profile_ok_(false), compiler_options_(compiler_options),
verification_results_(verification_results),
method_inliner_map_(method_inliner_map),
compiler_backend_(CompilerBackend::Create(compiler_backend_kind)),
@@ -338,6 +340,11 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
CHECK_PTHREAD_CALL(pthread_key_create, (&tls_key_, NULL), "compiler tls key");
+ // Read the profile file if one is provided.
+ if (profile_file != "") {
+ profile_ok_ = ReadProfile(profile_file);
+ }
+
dex_to_dex_compiler_ = reinterpret_cast<DexToDexCompilerFn>(ArtCompileDEX);
compiler_backend_->Init(*this);
@@ -1936,7 +1943,6 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t
} else {
MethodReference method_ref(&dex_file, method_idx);
bool compile = verification_results_->IsCandidateForCompilation(method_ref, access_flags);
-
if (compile) {
// NOTE: if compiler declines to compile this method, it will return NULL.
compiled_method = compiler_backend_->Compile(
@@ -2073,4 +2079,86 @@ void CompilerDriver::InstructionSetToLLVMTarget(InstructionSet instruction_set,
LOG(FATAL) << "Unknown instruction set: " << instruction_set;
}
}
+
+bool CompilerDriver::ReadProfile(const std::string& filename) {
+ VLOG(compiler) << "reading profile file " << filename;
+ struct stat st;
+ int err = stat(filename.c_str(), &st);
+ if (err == -1) {
+ VLOG(compiler) << "not found";
+ return false;
+ }
+ std::ifstream in(filename.c_str());
+ if (!in) {
+ VLOG(compiler) << "profile file " << filename << " exists but can't be opened";
+ VLOG(compiler) << "file owner: " << st.st_uid << ":" << st.st_gid;
+ VLOG(compiler) << "me: " << getuid() << ":" << getgid();
+ VLOG(compiler) << "file permissions: " << std::oct << st.st_mode;
+ VLOG(compiler) << "errno: " << errno;
+ return false;
+ }
+ // The first line contains summary information.
+ std::string line;
+ std::getline(in, line);
+ if (in.eof()) {
+ return false;
+ }
+ std::vector<std::string> summary_info;
+ Split(line, '/', summary_info);
+ if (summary_info.size() != 3) {
+ // Bad summary info. It should be count/total/bootpath
+ return false;
+ }
+ // This is the number of hits in all methods.
+ uint32_t total_count = 0;
+ for (int i = 0 ; i < 3; ++i) {
+ total_count += atoi(summary_info[0].c_str());
+ }
+
+ // Now read each line until the end of file. Each line consists of 3 fields separated by /
+ while (!in.eof()) {
+ std::getline(in, line);
+ if (in.eof()) {
+ break;
+ }
+ std::vector<std::string> info;
+ Split(line, '/', info);
+ if (info.size() != 3) {
+ // Malformed.
+ break;
+ }
+ const std::string& methodname = info[0];
+ uint32_t count = atoi(info[1].c_str());
+ uint32_t size = atoi(info[2].c_str());
+ double percent = (count * 100.0) / total_count;
+ // Add it to the profile map
+ profile_map_[methodname] = ProfileData(methodname, count, size, percent);
+ }
+ return true;
+}
+
+bool CompilerDriver::SkipCompilation(const std::string& method_name) {
+ if (!profile_ok_) {
+ return true;
+ }
+ constexpr double kThresholdPercent = 2.0; // Anything above this threshold will be compiled.
+
+ // First find the method in the profile map.
+ ProfileMap::iterator i = profile_map_.find(method_name);
+ if (i == profile_map_.end()) {
+ // Not in profile, no information can be determined.
+ VLOG(compiler) << "not compiling " << method_name << " because it's not in the profile";
+ return true;
+ }
+ const ProfileData& data = i->second;
+ bool compile = data.IsAbove(kThresholdPercent);
+ if (compile) {
+ LOG(INFO) << "compiling method " << method_name << " because its usage is " <<
+ data.GetPercent() << "%";
+ } else {
+ VLOG(compiler) << "not compiling method " << method_name << " because usage is too low ("
+ << data.GetPercent() << "%)";
+ }
+ return !compile;
+}
} // namespace art