OSDN Git Service

Support for multiple instances
authorDaniel Friederich <dfriederich@magicleap.com>
Wed, 12 Oct 2016 14:41:09 +0000 (09:41 -0500)
committerDaniel Friederich <dfriederich@magicleap.com>
Mon, 14 Nov 2016 22:38:47 +0000 (16:38 -0600)
Allows to use separate instances for separate perf.datai
files (and possibly also separate instances on separate threads)

Test: Tested by running report_sample.py
Change-Id: I0ebdb3c650a4540f07237b515d451d69ec3810e6

simpleperf/report_lib_interface.cpp
simpleperf/scripts/report_sample.py
simpleperf/scripts/simpleperf_report_lib.py

index 3653e0d..cdd9fb1 100644 (file)
@@ -24,6 +24,8 @@
 #include "thread_tree.h"
 #include "utils.h"
 
+class ReportLib;
+
 extern "C" {
 
 #define EXPORT __attribute__((visibility("default")))
@@ -59,17 +61,22 @@ struct CallChain {
   CallChainEntry* entries;
 };
 
+// Create a new instance,
+// pass the instance to the other functions below.
+ReportLib* CreateReportLib() EXPORT;
+void DestroyReportLib(ReportLib* report_lib) EXPORT;
+
 // Set log severity, different levels are:
 // verbose, debug, info, warning, error, fatal.
-bool SetLogSeverity(const char* log_level) EXPORT;
-bool SetSymfs(const char* symfs_dir) EXPORT;
-bool SetRecordFile(const char* record_file) EXPORT;
-void ShowIpForUnknownSymbol() EXPORT;
-
-Sample* GetNextSample() EXPORT;
-Event* GetEventOfCurrentSample() EXPORT;
-SymbolEntry* GetSymbolOfCurrentSample() EXPORT;
-CallChain* GetCallChainOfCurrentSample() EXPORT;
+bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT;
+bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT;
+bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT;
+void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT;
+
+Sample* GetNextSample(ReportLib* report_lib) EXPORT;
+Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT;
+SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT;
+CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT;
 }
 
 struct EventAttrWithName {
@@ -90,12 +97,9 @@ class ReportLib {
       : log_severity_(
             new android::base::ScopedLogSeverity(android::base::INFO)),
         record_filename_("perf.data"),
-        update_flag_(0) {}
-
-  static ReportLib& GetInstance() {
-    static ReportLib lib;
-    return lib;
-  }
+        current_thread_(nullptr),
+        update_flag_(0)
+         {}
 
   bool SetLogSeverity(const char* log_level);
 
@@ -272,32 +276,43 @@ CallChain* ReportLib::GetCallChainOfCurrentSample() {
   return &current_callchain_;
 }
 
-bool SetLogSeverity(const char* log_level) {
-  return ReportLib::GetInstance().SetLogSeverity(log_level);
+// Exported methods working with a client created instance
+ReportLib* CreateReportLib() {
+  return new ReportLib();
 }
 
-bool SetSymfs(const char* symfs_dir) {
-  return ReportLib::GetInstance().SetSymfs(symfs_dir);
+void DestroyReportLib(ReportLib* report_lib) {
+  delete report_lib;
 }
 
-bool SetRecordFile(const char* record_file) {
-  return ReportLib::GetInstance().SetRecordFile(record_file);
+bool SetLogSeverity(ReportLib* report_lib, const char* log_level) {
+  return report_lib->SetLogSeverity(log_level);
 }
 
-void ShowIpForUnknownSymbol() {
-  return ReportLib::GetInstance().ShowIpForUnknownSymbol();
+bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) {
+  return report_lib->SetSymfs(symfs_dir);
 }
 
-Sample* GetNextSample() { return ReportLib::GetInstance().GetNextSample(); }
+bool SetRecordFile(ReportLib* report_lib, const char* record_file) {
+  return report_lib->SetRecordFile(record_file);
+}
+
+void ShowIpForUnknownSymbol(ReportLib* report_lib) {
+  return report_lib->ShowIpForUnknownSymbol();
+}
+
+Sample* GetNextSample(ReportLib* report_lib) {
+  return report_lib->GetNextSample();
+}
 
-Event* GetEventOfCurrentSample() {
-  return ReportLib::GetInstance().GetEventOfCurrentSample();
+Event* GetEventOfCurrentSample(ReportLib* report_lib) {
+  return report_lib->GetEventOfCurrentSample();
 }
 
-SymbolEntry* GetSymbolOfCurrentSample() {
-  return ReportLib::GetInstance().GetSymbolOfCurrentSample();
+SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) {
+  return report_lib->GetSymbolOfCurrentSample();
 }
 
-CallChain* GetCallChainOfCurrentSample() {
-  return ReportLib::GetInstance().GetCallChainOfCurrentSample();
+CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) {
+  return report_lib->GetCallChainOfCurrentSample();
 }
index d0605cd..831baeb 100644 (file)
@@ -32,6 +32,7 @@ def usage():
 def report_sample(record_file, symfs_dir):
     """ read record_file, and print each sample"""
     lib = ReportLib()
+
     lib.ShowIpForUnknownSymbol()
     if symfs_dir is not None:
         lib.SetSymfs(symfs_dir)
@@ -41,6 +42,7 @@ def report_sample(record_file, symfs_dir):
     while True:
         sample = lib.GetNextSample()
         if sample is None:
+            lib.Close()
             break
         event = lib.GetEventOfCurrentSample()
         symbol = lib.GetSymbolOfCurrentSample()
index d4724b9..8b0e133 100644 (file)
@@ -61,6 +61,8 @@ class CallChainStructure(ct.Structure):
     _fields_ = [('nr', ct.c_uint32),
                 ('entries', ct.POINTER(CallChainEntryStructure))]
 
+class ReportLibStructure(ct.Structure):
+    _fields_ = []
 
 class ReportLib(object):
 
@@ -68,6 +70,9 @@ class ReportLib(object):
         if native_lib_path is None:
             native_lib_path = _get_script_path() + "/libsimpleperf_report.so"
         self._lib = ct.CDLL(native_lib_path)
+        self._CreateReportLibFunc = self._lib.CreateReportLib
+        self._CreateReportLibFunc.restype = ct.POINTER(ReportLibStructure)
+        self._DestroyReportLibFunc = self._lib.DestroyReportLib
         self._SetLogSeverityFunc = self._lib.SetLogSeverity
         self._SetSymfsFunc = self._lib.SetSymfs
         self._SetRecordFileFunc = self._lib.SetRecordFile
@@ -81,39 +86,55 @@ class ReportLib(object):
         self._GetCallChainOfCurrentSampleFunc = self._lib.GetCallChainOfCurrentSample
         self._GetCallChainOfCurrentSampleFunc.restype = ct.POINTER(
             CallChainStructure)
+        self._instance = self._CreateReportLibFunc()
+        assert(not _is_null(self._instance))
+
+    def Close(self):
+        if self._instance is None:
+            return
+        self._DestroyReportLibFunc(self._instance)
+        self._instance = None
 
     def SetLogSeverity(self, log_level='info'):
         """ Set log severity of native lib, can be verbose,debug,info,error,fatal."""
-        assert(self._SetLogSeverityFunc(log_level))
+        cond = self._SetLogSeverityFunc(self.getInstance(), log_level)
+        assert(cond)
 
     def SetSymfs(self, symfs_dir):
         """ Set directory used to find symbols."""
-        assert(self._SetSymfsFunc(symfs_dir))
+        cond = self._SetSymfsFunc(self.getInstance(), symfs_dir)
+        assert(cond)
 
     def SetRecordFile(self, record_file):
         """ Set the path of record file, like perf.data."""
-        assert(self._SetRecordFileFunc(record_file))
+        cond = self._SetRecordFileFunc(self.getInstance(), record_file)
+        assert(cond)
 
     def ShowIpForUnknownSymbol(self):
-        self._ShowIpForUnknownSymbolFunc()
+        self._ShowIpForUnknownSymbolFunc(self.getInstance())
 
     def GetNextSample(self):
-        sample = self._GetNextSampleFunc()
+        sample = self._GetNextSampleFunc(self.getInstance())
         if _is_null(sample):
             return None
         return sample
 
     def GetEventOfCurrentSample(self):
-        event = self._GetEventOfCurrentSampleFunc()
+        event = self._GetEventOfCurrentSampleFunc(self.getInstance())
         assert(not _is_null(event))
         return event
 
     def GetSymbolOfCurrentSample(self):
-        symbol = self._GetSymbolOfCurrentSampleFunc()
+        symbol = self._GetSymbolOfCurrentSampleFunc(self.getInstance())
         assert(not _is_null(symbol))
         return symbol
 
     def GetCallChainOfCurrentSample(self):
-        callchain = self._GetCallChainOfCurrentSampleFunc()
+        callchain = self._GetCallChainOfCurrentSampleFunc(self.getInstance())
         assert(not _is_null(callchain))
         return callchain
+
+    def getInstance(self):
+        if self._instance is None:
+            raise Exception("Instance is Closed")
+        return self._instance