Bug 733861 - Use std::ostreams for profile stringification. r=BenWa
authorMarkus Stange <mstange@themasta.com>
Fri, 23 Mar 2012 20:09:27 +0100
changeset 93502 8b15746f43a1184d0747d270354b29233fc5fdcf
parent 93501 b28c614c6fe3de1fe34c972cb9eadb67983594b0
child 93503 1b05e9751f3477275a7bb566fc20f3941411af1d
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa
bugs733861
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 733861 - Use std::ostreams for profile stringification. r=BenWa
build/stdc++compat.cpp
tools/profiler/TableTicker.cpp
--- a/build/stdc++compat.cpp
+++ b/build/stdc++compat.cpp
@@ -54,19 +54,17 @@
 namespace std {
 #if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 9)
     /* Instantiate these templates to avoid GLIBCXX_3.4.9 symbol versions */
     template ostream& ostream::_M_insert(double);
     template ostream& ostream::_M_insert(long);
     template ostream& ostream::_M_insert(unsigned long);
     template ostream& ostream::_M_insert(long long);
     template ostream& ostream::_M_insert(unsigned long long);
-#ifdef DEBUG
     template ostream& ostream::_M_insert(const void*);
-#endif
     template ostream& __ostream_insert(ostream&, const char*, streamsize);
     template istream& istream::_M_extract(double&);
 #endif
 #if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 14)
     /* Instantiate these templates to avoid GLIBCXX_3.4.14 symbol versions
      * depending on optimization level */
     template char *string::_S_construct_aux_2(size_type, char, allocator<char> const&);
 #ifdef _GLIBCXX_USE_WCHAR_T
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -33,23 +33,25 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <string>
 #include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
 #include "sps_sampler.h"
 #include "platform.h"
 #include "nsXULAppAPI.h"
 #include "nsThreadUtils.h"
 #include "prenv.h"
 #include "shared-libraries.h"
-#include "mozilla/StringBuilder.h"
 #include "mozilla/StackWalk.h"
 #include "JSObjectBuilder.h"
 
 // we eventually want to make this runtime switchable
 #if defined(MOZ_PROFILING) && (defined(XP_UNIX) && !defined(XP_MACOSX))
  #ifndef ANDROID
   #define USE_BACKTRACE
  #endif
@@ -142,17 +144,17 @@ public:
   { }
 
   ProfileEntry(char aTagName, uintptr_t aTagOffset)
     : mTagOffset(aTagOffset)
     , mLeafAddress(0)
     , mTagName(aTagName)
   { }
 
-  string TagToString(ThreadProfile *profile);
+  friend std::ostream& operator<<(std::ostream& stream, const ProfileEntry& entry);
 
 private:
   friend class ThreadProfile;
   union {
     const char* mTagData;
     double mTagFloat;
     Address mTagAddress;
     uintptr_t mTagOffset;
@@ -253,24 +255,17 @@ public:
   // |ABCDEFdefghijklmnopqrstuvwxyz| -> 'defghijkl'
   // |-----------------------------|
 
   void erase()
   {
     mWritePos = mLastFlushPos;
   }
 
-  void ToString(StringBuilder &profile)
-  {
-    int readPos = mReadPos;
-    while (readPos != mLastFlushPos) {
-      profile.Append(mEntries[readPos].TagToString(this).c_str());
-      readPos = (readPos + 1) % mEntrySize;
-    }
-  }
+  friend std::ostream& operator<<(std::ostream& stream, const ThreadProfile& profile);
 
   JSObject *ToJSObject(JSContext *aCx)
   {
     JSObjectBuilder b(aCx);
 
     JSObject *profile = b.CreateObject();
     JSObject *samples = b.CreateArray();
     b.DefineProperty(profile, "samples", samples);
@@ -304,26 +299,16 @@ public:
           }
       }
     }
     mReadPos = oldReadPos;
 
     return profile;
   }
 
-  void WriteProfile(FILE* stream)
-  {
-    int readPos = mReadPos;
-    while (readPos != mLastFlushPos) {
-      string tag = mEntries[readPos].TagToString(this);
-      fwrite(tag.data(), 1, tag.length(), stream);
-      readPos = (readPos + 1) % mEntrySize;
-    }
-  }
-
   ProfileStack* GetStack()
   {
     return mStack;
   }
 private:
   // Circular buffer 'Keep One Slot Open' implementation
   // for simplicity
   ProfileEntry *mEntries;
@@ -426,20 +411,21 @@ public:
     // Expand %TEMP% on Windows
     {
       char tmp[MAXPATHLEN];
       ExpandEnvironmentStringsA(buff, tmp, mozilla::ArrayLength(tmp));
       strcpy(buff, tmp);
     }
 #endif
 
-    FILE* stream = ::fopen(buff, "w");
-    if (stream) {
-      t->GetPrimaryThreadProfile()->WriteProfile(stream);
-      ::fclose(stream);
+    std::ofstream stream;
+    stream.open(buff);
+    if (stream.is_open()) {
+      stream << *(t->GetPrimaryThreadProfile());
+      stream.close();
       LOG("Saved to " FOLDER "profile_TYPE_PID.txt");
     } else {
       LOG("Fail to open profile log file.");
     }
 
     return NS_OK;
   }
 };
@@ -670,41 +656,42 @@ void TableTicker::Tick(TickSample* sampl
     mPrimaryThreadProfile.flush();
 
   if (!mJankOnly && !sLastTracerEvent.IsNull() && sample) {
     TimeDuration delta = sample->timestamp - sLastTracerEvent;
     mPrimaryThreadProfile.addTag(ProfileEntry('r', delta.ToMilliseconds()));
   }
 }
 
-string ProfileEntry::TagToString(ThreadProfile *profile)
+std::ostream& operator<<(std::ostream& stream, const ThreadProfile& profile)
 {
-  string tag = "";
-  if (mTagName == 'r') {
-    char buff[50];
-    snprintf(buff, 50, "%-40f", mTagFloat);
-    tag += string(1, mTagName) + string("-") + string(buff) + string("\n");
-  } else if (mTagName == 'l') {
-    char tagBuff[1024];
-    Address pc = mTagAddress;
-    snprintf(tagBuff, 1024, "l-%p\n", pc);
-    tag += string(tagBuff);
+  int readPos = profile.mReadPos;
+  while (readPos != profile.mLastFlushPos) {
+    stream << profile.mEntries[readPos];
+    readPos = (readPos + 1) % profile.mEntrySize;
+  }
+  return stream;
+}
+
+std::ostream& operator<<(std::ostream& stream, const ProfileEntry& entry)
+{
+  if (entry.mTagName == 'r') {
+    stream << entry.mTagName << "-" << std::fixed << entry.mTagFloat << "\n";
+  } else if (entry.mTagName == 'l') {
+    stream << entry.mTagName << "-" << static_cast<const void*>(entry.mTagData) << "\n";
   } else {
-    tag += string(1, mTagName) + string("-") + string(mTagData) + string("\n");
+    stream << entry.mTagName << "-" << entry.mTagData << "\n";
   }
 
 #ifdef ENABLE_SPS_LEAF_DATA
-  if (mLeafAddress) {
-    char tagBuff[1024];
-    unsigned long pc = (unsigned long)mLeafAddress;
-    snprintf(tagBuff, 1024, "l-%llu\n", pc);
-    tag += string(tagBuff);
+  if (entry.mLeafAddress) {
+    stream << entry.mTagName << "-" << entry.mLeafAddress << "\n";
   }
 #endif
-  return tag;
+  return stream;
 }
 
 void mozilla_sampler_init()
 {
   // TODO linux port: Use TLS with ifdefs
   if (!mozilla::tls::create(&pkey_stack) ||
       !mozilla::tls::create(&pkey_ticker)) {
     LOG("Failed to init.");
@@ -762,21 +749,22 @@ void mozilla_sampler_save()
 
 char* mozilla_sampler_get_profile()
 {
   TableTicker *t = mozilla::tls::get<TableTicker>(pkey_ticker);
   if (!t) {
     return NULL;
   }
 
-  StringBuilder profile;
-  t->GetPrimaryThreadProfile()->ToString(profile);
+  std::stringstream profile;
+  profile << *(t->GetPrimaryThreadProfile());
 
-  char *rtn = (char*)malloc( (profile.Length()+1) * sizeof(char) );
-  strcpy(rtn, profile.Buffer());
+  std::string profileString = profile.str();
+  char *rtn = (char*)malloc( (profileString.length() + 1) * sizeof(char) );
+  strcpy(rtn, profileString.c_str());
   return rtn;
 }
 
 JSObject *mozilla_sampler_get_profile_data(JSContext *aCx)
 {
   TableTicker *t = mozilla::tls::get<TableTicker>(pkey_ticker);
   if (!t) {
     return NULL;