Bug 733861 - Use std::ostreams for profile stringification. r=BenWa
☠☠ backed out by add2ed43cc05 ☠ ☠
authorMarkus Stange <mstange@themasta.com>
Thu, 22 Mar 2012 23:40:33 +0100
changeset 91898 f42ea2a158e451a490db2c0435fc57885ac349be
parent 91897 7c54ec42cb08cf2f6ce79510ade6945ff4a9459f
child 91899 6c8d1da1e1db869a7a9588be955142085810c445
push idunknown
push userunknown
push dateunknown
reviewersBenWa
bugs733861
milestone14.0a1
Bug 733861 - Use std::ostreams for profile stringification. r=BenWa
tools/profiler/TableTicker.cpp
--- 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 Profile& 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 Profile& 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;