Clean up the sampling profiler

- rename variables/fields names to match the code style (use
_underscore_names_)
- extract common property parsing in utils.cc
- fail to load profile file if any line is malformed
- added ProfileFile to manage the profile data generate in the previous
runs (replaces ProfileHelper and nests ProfileData)

Bug: 12877748
Change-Id: Ie7bda30bfdeb7e78534c986615b0649eac12a97b
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index a0a294a..585c88e 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -37,13 +37,10 @@
 #include "scoped_thread_state_change.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
+#include "utils.h"
 #include "well_known_classes.h"
 #include "zip_archive.h"
 
-#ifdef HAVE_ANDROID_OS
-#include "cutils/properties.h"
-#endif
-
 namespace art {
 
 // A smart pointer that provides read-only access to a Java string's UTF chars.
@@ -250,25 +247,6 @@
   close(fd2);
 }
 
-static double GetDoubleProperty(const char* property, double minValue, double maxValue, double defaultValue) {
-#ifndef HAVE_ANDROID_OS
-  return defaultValue;
-#else
-  char buf[PROP_VALUE_MAX];
-  char* endptr;
-
-  property_get(property, buf, "");
-  double value = strtod(buf, &endptr);
-
-  if (value == 0 && endptr == buf) {
-    value = defaultValue;
-  } else if (value < minValue || value > maxValue) {
-    value = defaultValue;
-  }
-  return value;
-#endif
-}
-
 static jboolean IsDexOptNeededInternal(JNIEnv* env, const char* filename,
     const char* pkgname, const char* instruction_set, const jboolean defer) {
   const bool kVerboseLogging = false;  // Spammy logging.
@@ -379,42 +357,46 @@
       // 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 topKThreshold = GetDoubleProperty("dalvik.vm.profiler.dex2oat.compile_thr", 10.0, 90.0, 90.0);
-      double changeThreshold = GetDoubleProperty("dalvik.vm.profiler.dex2oat.change_thr", 1.0, 90.0, 10.0);
-      double changePercent = 0.0;
-      std::set<std::string> newTopK, oldTopK;
-      bool newOk = ProfileHelper::LoadTopKSamples(newTopK, profile_file, topKThreshold);
-      bool oldOk = ProfileHelper::LoadTopKSamples(oldTopK, prev_profile_file, topKThreshold);
-      if (!newOk || !oldOk) {
+      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 change_percent = 0.0;
+      ProfileFile new_profile, old_profile;
+      bool new_ok = new_profile.LoadFile(profile_file);
+      bool old_ok = old_profile.LoadFile(prev_profile_file);
+      if (!new_ok || !old_ok) {
         if (kVerboseLogging) {
           LOG(INFO) << "DexFile_isDexOptNeeded Ignoring invalid profiles: "
-                    << (newOk ?  "" : profile_file) << " " << (oldOk ? "" : prev_profile_file);
+                    << (new_ok ?  "" : profile_file) << " " << (old_ok ? "" : prev_profile_file);
         }
-      } else if (newTopK.empty()) {
-        if (kVerboseLogging) {
-          LOG(INFO) << "DexFile_isDexOptNeeded empty profile: " << profile_file;
-        }
-        // If the new topK is empty we shouldn't optimize so we leave the changePercent at 0.0.
       } else {
-        std::set<std::string> diff;
-        std::set_difference(newTopK.begin(), newTopK.end(), oldTopK.begin(), oldTopK.end(),
-          std::inserter(diff, diff.end()));
-        // TODO: consider using the usedPercentage instead of the plain diff count.
-        changePercent = 100.0 * static_cast<double>(diff.size()) / static_cast<double>(newTopK.size());
-        if (kVerboseLogging) {
-          std::set<std::string>::iterator end = diff.end();
-          for (std::set<std::string>::iterator it = diff.begin(); it != end; it++) {
-            LOG(INFO) << "DexFile_isDexOptNeeded new in topK: " << *it;
+        std::set<std::string> new_top_k, old_top_k;
+        new_profile.GetTopKSamples(new_top_k, top_k_threshold);
+        old_profile.GetTopKSamples(old_top_k, top_k_threshold);
+        if (new_top_k.empty()) {
+          if (kVerboseLogging) {
+            LOG(INFO) << "DexFile_isDexOptNeeded empty profile: " << profile_file;
+          }
+          // If the new topK is empty we shouldn't optimize so we leave the change_percent at 0.0.
+        } else {
+          std::set<std::string> diff;
+          std::set_difference(new_top_k.begin(), new_top_k.end(), old_top_k.begin(), old_top_k.end(),
+            std::inserter(diff, diff.end()));
+          // TODO: consider using the usedPercentage instead of the plain diff count.
+          change_percent = 100.0 * static_cast<double>(diff.size()) / static_cast<double>(new_top_k.size());
+          if (kVerboseLogging) {
+            std::set<std::string>::iterator end = diff.end();
+            for (std::set<std::string>::iterator it = diff.begin(); it != end; it++) {
+              LOG(INFO) << "DexFile_isDexOptNeeded new in topK: " << *it;
+            }
           }
         }
       }
 
-      if (changePercent > changeThreshold) {
+      if (change_percent > change_threshold) {
         if (kReasonLogging) {
           LOG(INFO) << "DexFile_isDexOptNeeded size of new profile file " << profile_file <<
           " is significantly different from old profile file " << prev_profile_file << " (top "
-          << topKThreshold << "% samples changed in proportion of " << changePercent << "%)";
+          << top_k_threshold << "% samples changed in proportion of " << change_percent << "%)";
         }
         if (!defer) {
           CopyProfileFile(profile_file.c_str(), prev_profile_file.c_str());