summaryrefslogtreecommitdiff
path: root/compiler/driver/compiler_driver.cc
diff options
context:
space:
mode:
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 d3d58c919f..a46015d0f9 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