Belle II Software development
ProcessStatisticsPython Class Reference

Python interface for ProcessStatistics. More...

#include <ProcessStatisticsPython.h>

Public Member Functions

 ProcessStatisticsPython (ModuleStatistics::EStatisticCounters type=ModuleStatistics::c_Event, const std::vector< ModuleStatistics > &modules={})
 Construct a new object to show statistics for a given call type.
 
 ProcessStatisticsPython (const ProcessStatisticsPython &)=default
 Default copy constructor.
 
ProcessStatisticsPythonoperator= (const ProcessStatisticsPython &)=default
 Default assignment operator.
 
 ~ProcessStatisticsPython ()=default
 Default destructor.
 
ProcessStatisticsgetWrapped ()
 Get wrapped ProcessStatistics object.
 
std::string getStatisticsString ()
 Return string with statistics for all selected modules.
 
std::string getStatisticsStringHTML ()
 Return string with statistics for all selected modules as html table.
 
ProcessStatisticsPython getModuleStatistics (ModuleStatistics::EStatisticCounters type, const boost::python::list &modulesPyList)
 Get a new statistics object for a different counter/different list of modules.
 
const ModuleStatisticsget (const std::shared_ptr< Module > &module)
 Get statistics for given module.
 
const ModuleStatisticsgetGlobal ()
 Get statistics for the framework itself.
 
boost::python::list getAll ()
 Get statistics for all modules as python list.
 
void clear ()
 Clear collected statistics but keep names of modules.
 
void csv (const char *filename)
 Write statistics to a csv file.
 

Static Public Member Functions

static void exposePythonAPI ()
 Define python wrappers to make functionality available in python.
 

Private Attributes

ModuleStatistics::EStatisticCounters m_type {ModuleStatistics::c_Event}
 Which counter to show when printing the statistics.
 
std::vector< ModuleStatisticsm_modules
 Which modules to show.
 

Detailed Description

Python interface for ProcessStatistics.

Since ProcessStatistics itself resides in the data store, this wraps around it to export some functionality to python.

Definition at line 31 of file ProcessStatisticsPython.h.

Constructor & Destructor Documentation

◆ ProcessStatisticsPython()

Construct a new object to show statistics for a given call type.

Possibly also restricting the list of modules to be shown

Definition at line 34 of file ProcessStatisticsPython.h.

35 {}): m_type{type}, m_modules{modules} {}

Member Function Documentation

◆ clear()

void clear ( )

Clear collected statistics but keep names of modules.

Definition at line 95 of file ProcessStatisticsPython.cc.

96{
97 if (!getWrapped())
98 return;
99 getWrapped()->clear();
100}
ProcessStatistics * getWrapped()
Get wrapped ProcessStatistics object.
virtual void clear() override
Clear collected statistics but keep names of modules.

◆ csv()

void csv ( const char * filename)

Write statistics to a csv file.

Definition at line 102 of file ProcessStatisticsPython.cc.

103{
104 if (!getWrapped())
105 return;
106 getWrapped()->write_csv(filename);
107}
void write_csv(const char *filename="ProcessStatistics.csv") const
Write process statistics to a csv file.

◆ exposePythonAPI()

void exposePythonAPI ( )
static

Define python wrappers to make functionality available in python.

Definition at line 110 of file ProcessStatisticsPython.cc.

111{
112 // to avoid confusion between std::arg and boost::python::arg we want a shorthand namespace as well
113 namespace bp = boost::python;
114
115 //Reference to global scope
116 scope global;
117
118 docstring_options options(true, true, false); //userdef, py sigs, c++ sigs
119
120 //Wrap ProcessStatisticsPython as non-copy and non-instantiable in python
121 class_<ProcessStatisticsPython> stats("ProcessStatistics", R"DOCSTRING(
122Interface for retrieving statistics about module execution at runtime or after
123:py:func:`basf2.process()` returns. Should be accessed through a global instance `basf2.statistics`.
124
125Statistics for `event() <Module.event()>` calls are available as a string representation of the object:
126
127>>> from basf2 import statistics
128>>> print(statistics)
129=================================================================================
130Name | Calls | Memory(MB) | Time(s) | Time(ms)/Call
131=================================================================================
132RootInput | 101 | 0 | 0.01 | 0.05 +- 0.02
133RootOutput | 100 | 0 | 0.02 | 0.20 +- 0.87
134ProgressBar | 100 | 0 | 0.00 | 0.00 +- 0.00
135=================================================================================
136Total | 101 | 0 | 0.03 | 0.26 +- 0.86
137=================================================================================
138
139This provides information on the number of calls, elapsed time, and the average
140difference in resident memory before and after the `event() <Module.event>` call.
141
142.. note::
143
144 The module responsible for reading (or generating) events usually has one
145 additional event() call which is used to determine whether event processing
146 should stop.
147
148.. warning::
149
150 Memory consumption is reporting the difference in memory usage as reported
151 by the kernel before and after the call. This is not the maximum memory the
152 module has consumed. Negative values indicate that this module has freed
153 memory which was allocated in other modules or function calls.
154
155Information on other calls like `initialize() <Module.initialize>`,
156`terminate() <Module.terminate>`, etc. are also available through the different
157counters defined in `StatisticCounters`:
158
159>>> print(statistics(statistics.INIT))
160>>> print(statistics(statistics.BEGIN_RUN))
161>>> print(statistics(statistics.END_RUN))
162>>> print(statistics(statistics.TERM))
163)DOCSTRING", no_init);
164
165 stats
166 .def("get", &ProcessStatisticsPython::get, return_value_policy<reference_existing_object>(), bp::arg("module"),
167 "Get `ModuleStatistics` for given Module.")
168 .def("get_global", &ProcessStatisticsPython::getGlobal, return_value_policy<reference_existing_object>(),
169 "Get global `ModuleStatistics` containing total elapsed time etc.")
170 .def("clear", &ProcessStatisticsPython::clear, "Clear collected statistics but keep names of modules")
171 .def_readonly("modules", &ProcessStatisticsPython::getAll, "List of all `ModuleStatistics` objects.")
172 .def("csv", &ProcessStatisticsPython::csv, "Write statistics to a csv file")
173 ;
174
175 //Set scope to current class
176 scope statistics{stats};
177 //Define enum for all the counter types in scope of class
178 enum_<ModuleStatistics::EStatisticCounters>("StatisticCounters", R"DOCSTRING(
179Available types of statistic counters (corresponds to Module functions)
180
181.. attribute:: INIT
182
183Time spent or memory used in the `initialize() <Module.initialize>` function
184
185.. attribute:: BEGIN_RUN
186
187Time spent or memory used in the `beginRun() <Module.beginRun>` function
188
189.. attribute:: EVENT
190
191Time spent or memory used in the `event() <Module.event>` function
192
193.. attribute:: END_RUN
194
195Time spent or memory used in the `endRun() <Module.endRun>` function
196
197.. attribute:: TERM
198
199Time spent or memory used in the `terminate() <Module.terminate>` function
200
201.. attribute:: TOTAL
202
203Time spent or memory used in any module function. This is the sum of all of the above.
204
205)DOCSTRING")
206 .value("INIT", ModuleStatistics::c_Init)
207 .value("BEGIN_RUN", ModuleStatistics::c_BeginRun)
208 .value("EVENT", ModuleStatistics::c_Event)
209 .value("END_RUN", ModuleStatistics::c_EndRun)
210 .value("TERM", ModuleStatistics::c_Term)
211 .value("TOTAL", ModuleStatistics::c_Total)
212 .export_values()
213 ;
214
215 {
216 // the overloaded __str__ and __call__ give very confusing signatures so hand-craft doc string.
217 docstring_options custom_options(true, false, false); //userdef, py sigs, c++ sigs
218 stats
220 "Return the event statistics as a string in a human readable form")
222 "Return an html representation of the statistics (used by ipython/jupyter)")
223 .def("__call__", &ProcessStatisticsPython::getModuleStatistics, (bp::arg("counter") = ModuleStatistics::EStatisticCounters::c_Event, bp::arg("modules") = boost::python::list()),
224 R"DOCSTRING(__call__(counter=StatisticCounters.EVENT, modules=None)
225
226Calling the statistics object directly like a function will return a string
227with the execution statistics in human readable form.
228
229Parameters:
230 counter (StatisticCounters): Which counter to use
231 modules (list[Module]): A list of modules to include in the returned string.
232 If omitted the statistics for all modules will be included.
233
234* print the `beginRun() <Module.beginRun>` statistics for all modules:
235
236 >>> print(statistics(statistics.BEGIN_RUN))
237
238* print the total execution times and memory consumption but only for the
239 modules ``module1`` and ``module2``
240
241 >>> print(statistics(statistics.TOTAL, [module1, module2]))
242
243* print the event statistics (default) for only two modules
244
245 >>> print(statistics(modules=[module1, module2]))
246)DOCSTRING")
247 ;
248 }
249
250 //Wrap statistics class. The default boost python docstring signature is way
251 //to noisy for these simple getters so this time we do it ourselves ...
252 docstring_options new_options(true, false, false); //userdef, py sigs, c++ sigs
253 class_<ModuleStatistics>("ModuleStatistics", "Execution statistics for a single module. "
254 "All member functions take exactly one argument to select which "
255 "counter to query which defaults to `StatisticCounters.TOTAL` if omitted.")
256 .add_property("name", make_function(&ModuleStatistics::getName, return_value_policy<copy_const_reference>()),
const std::string & getName() const
Return the previously set name.
@ c_Init
Counting time/calls in initialize()
@ c_EndRun
Counting time/calls in endRun()
@ c_Term
Counting time/calls in terminate()
@ c_BeginRun
Counting time/calls in beginRun()
@ c_Event
Counting time/calls in event()
@ c_Total
Sum of the above.
std::string getStatisticsStringHTML()
Return string with statistics for all selected modules as html table.
ProcessStatisticsPython getModuleStatistics(ModuleStatistics::EStatisticCounters type, const boost::python::list &modulesPyList)
Get a new statistics object for a different counter/different list of modules.
void csv(const char *filename)
Write statistics to a csv file.
const ModuleStatistics * get(const std::shared_ptr< Module > &module)
Get statistics for given module.
std::string getStatisticsString()
Return string with statistics for all selected modules.
void clear()
Clear collected statistics but keep names of modules.
boost::python::list getAll()
Get statistics for all modules as python list.
const ModuleStatistics * getGlobal()
Get statistics for the framework itself.

◆ get()

const ModuleStatistics * get ( const std::shared_ptr< Module > & module)

Get statistics for given module.

Definition at line 81 of file ProcessStatisticsPython.cc.

82{
83 if (!getWrapped())
84 return nullptr;
85 return &getWrapped()->getStatistics(module.get());
86}
ModuleStatistics & getStatistics(const Module *module)
Get statistics for single module.

◆ getAll()

boost::python::list getAll ( )

Get statistics for all modules as python list.

Definition at line 70 of file ProcessStatisticsPython.cc.

71{
72 boost::python::list result;
73 if (!getWrapped())
74 return result;
75 for (auto& module : (m_modules.empty()) ? getWrapped()->getAll() : m_modules) {
76 result.append(module);
77 }
78 return result;
79}
std::vector< ModuleStatistics > m_modules
Which modules to show.

◆ getGlobal()

const ModuleStatistics * getGlobal ( )

Get statistics for the framework itself.

Definition at line 88 of file ProcessStatisticsPython.cc.

89{
90 if (!getWrapped())
91 return nullptr;
92 return &getWrapped()->getGlobal();
93
94}
const ModuleStatistics & getGlobal() const
Get global statistics.

◆ getModuleStatistics()

ProcessStatisticsPython getModuleStatistics ( ModuleStatistics::EStatisticCounters type,
const boost::python::list & modulesPyList )

Get a new statistics object for a different counter/different list of modules.

Definition at line 53 of file ProcessStatisticsPython.cc.

55{
56 if (!getWrapped())
58
59 std::vector<ModuleStatistics> moduleStats;
60 auto modules = PyObjConvUtils::convertPythonObject(modulesPyList, std::vector<ModulePtr>());
61 for (const ModulePtr& ptr : modules) {
62 ModuleStatistics& stats = getWrapped()->getStatistics(ptr.get());
63 //Name could be empty if module has never been called
64 if (stats.getName().empty()) stats.setName(ptr->getName());
65 moduleStats.push_back(stats);
66 }
67 return ProcessStatisticsPython(type, moduleStats);
68}
ProcessStatisticsPython(ModuleStatistics::EStatisticCounters type=ModuleStatistics::c_Event, const std::vector< ModuleStatistics > &modules={})
Construct a new object to show statistics for a given call type.
std::shared_ptr< Module > ModulePtr
Defines a pointer to a module object as a boost shared pointer.
Definition Module.h:43
Scalar convertPythonObject(const boost::python::object &pyObject, Scalar)
Convert from Python to given type.

◆ getStatisticsString()

string getStatisticsString ( )

Return string with statistics for all selected modules.

If none are selected show all modules

Can be used in steering file with 'print(statistics)'.

Definition at line 33 of file ProcessStatisticsPython.cc.

34{
35 if (!getWrapped())
36 return "";
37 if (getWrapped()->getStatisticsPrintStatus(m_type))
38 return "";
40 return getWrapped()->getStatisticsString(m_type, m_modules.empty() ? nullptr : &m_modules);
41}
ModuleStatistics::EStatisticCounters m_type
Which counter to show when printing the statistics.
std::string getStatisticsString(ModuleStatistics::EStatisticCounters type=ModuleStatistics::c_Event, const std::vector< Belle2::ModuleStatistics > *modules=nullptr, bool html=false) const
Return string with statistics for all modules.
void setStatisticsPrintStatus(ModuleStatistics::EStatisticCounters type, bool printStatus)
Set print status of statistics.

◆ getStatisticsStringHTML()

string getStatisticsStringHTML ( )

Return string with statistics for all selected modules as html table.

If none are selected show all modules

Is used in Jupyter notebooks

Definition at line 43 of file ProcessStatisticsPython.cc.

44{
45 if (!getWrapped())
46 return "";
47 if (getWrapped()->getStatisticsPrintStatus(m_type))
48 return "";
50 return getWrapped()->getStatisticsString(m_type, m_modules.empty() ? nullptr : &m_modules, true);
51}

◆ getWrapped()

ProcessStatistics * getWrapped ( )

Get wrapped ProcessStatistics object.

Definition at line 21 of file ProcessStatisticsPython.cc.

22{
23 StoreObjPtr<ProcessStatistics> stats("", DataStore::c_Persistent);
24 if (!stats) {
25 if (!Environment::Instance().getDryRun()) {
26 B2ERROR("ProcessStatistics data object is not available, you either didn't enable statistics with --stats or didn't run process(path) yet.");
27 }
28 return nullptr;
29 }
30 return &(*stats);
31}
@ c_Persistent
Object is available during entire execution time.
Definition DataStore.h:60
static Environment & Instance()
Static method to get a reference to the Environment instance.

Member Data Documentation

◆ m_modules

std::vector<ModuleStatistics> m_modules
private

Which modules to show.

If empty, show all modules

Definition at line 86 of file ProcessStatisticsPython.h.

◆ m_type

Which counter to show when printing the statistics.

Definition at line 84 of file ProcessStatisticsPython.h.

84{ModuleStatistics::c_Event};

The documentation for this class was generated from the following files: