Source code for Muscat.Helpers.Profiler
# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
import cProfile
import pstats
import io
from collections import OrderedDict
import numpy as np
from Muscat.Helpers.Interpolation import BinarySearch
[docs]
class Profiler():
"""Class to help profiling code, this is a very simple approach. it uses
cProfile and pstats to do all the work.
myProfiler = Profiler(0.2)
myProfiler.Start()
#do some work
time.sleep(0.02)
print("Hello")
a = 3 + 4
myProfiler.Stop()
print(myProfiler)
"""
def __init__(self, discardedPortion: float = 0.2, timerSignificantDigits: int = 3):
"""_summary_
Parameters
----------
discardedPortion : float, optional
discarded portion on the output , by default 0.2 (20%)
timerSignificantDigits : int, optional
Number of digits to use for the times printed, by default 3
"""
self.pr = cProfile.Profile()
self.s = io.StringIO()
self.ps = None
self.discardedPortion = discardedPortion
self.timerSignificantDigits = timerSignificantDigits
self.totTimes = None
self.cumTimes = None
self.sumTotTime = None
self.sumCumTime = None
[docs]
def Start(self) -> None:
"""Start the profiling
"""
self.pr.enable()
[docs]
def Stop(self) -> None:
"""Stop the profiling
"""
self.pr.disable()
self.ps = pstats.Stats(self.pr, stream=self.s).sort_stats('cumulative')
self.ps.reverse_order()
self.ps.print_stats()
lines = self.s.getvalue().split('\n')[5:-3]
functionNames = [l[46:][-60:] for l in lines]
parsing = np.array([l.split()[:5] for l in lines])
totalTimes = np.array(parsing[:, 1], dtype=float)
cumulatedTimes = np.array(parsing[:, 3], dtype=float)
self.sumTotTime = np.sum(totalTimes)
self.sumCumTime = np.sum(cumulatedTimes)
totalTimes = totalTimes / np.sum(totalTimes)
cumulatedTimes = cumulatedTimes / np.sum(cumulatedTimes)
totalTimesArgSort = np.argsort(totalTimes)
cumulatedTimesArgSort = np.argsort(cumulatedTimes)
cumulatedSumTotalTimes = np.cumsum(totalTimes[totalTimesArgSort])
cumulatedSumCumulatedTimes = np.cumsum(cumulatedTimes[cumulatedTimesArgSort])
totalTimesArgSortInv = totalTimesArgSort[BinarySearch(cumulatedSumTotalTimes, self.discardedPortion)+1:][::-1]
cumTimesArgSortInv = cumulatedTimesArgSort[BinarySearch(cumulatedSumCumulatedTimes, self.discardedPortion)+1:][::-1]
totalTimes = totalTimes[totalTimesArgSortInv]
totalTimes = np.hstack((totalTimes, 1 - np.sum(totalTimes)))
cumulatedTimes = cumulatedTimes[cumTimesArgSortInv]
cumulatedTimes = np.hstack((cumulatedTimes, 1 - np.sum(cumulatedTimes)))
functionNamesTotalTime = [functionNames[i] for i in totalTimesArgSortInv] + ["REMAINING"]
functionNamesCumTime = [functionNames[i] for i in cumTimesArgSortInv] + ["REMAINING"]
self.totTimes = OrderedDict(zip(totalTimes, functionNamesTotalTime))
self.cumTimes = OrderedDict(zip(cumulatedTimes, functionNamesCumTime))
def __str__(self) -> str:
"""Return a string with all the collected information
Returns
-------
str
Teh description
"""
from Muscat.Helpers.TextFormatHelper import TFormat
string = TFormat.InBlue("Profiler")+" discarding "
string += str(int(100.*self.discardedPortion))+"% of the smallest functions\n"
string += TFormat.InRed("Total times:\n")
for part, name in self.totTimes.items():
string += TFormat.InGreen(TFormat.Center(name, width=70))+": "+str(round(100.*part, 2))
string += "% ("+str(round(self.sumTotTime*part, self.timerSignificantDigits))+"s)\n"
string += TFormat.InRed("Cumulated times:\n")
for part, name in self.cumTimes.items():
string += TFormat.InGreen(TFormat.Center(name, width=70))+": "+str(round(100.*part, 2))
string += "% ("+str(round(self.sumCumTime*part, self.timerSignificantDigits))+"s)\n"
return string
[docs]
def CheckIntegrity(GUI:bool=False):
import time
p = Profiler(0.2)
p.Start()
time.sleep(0.02)
print("Hello")
a = 3 + 4
p.Stop()
print(p)
return "ok"
if __name__ == '__main__':
print(CheckIntegrity(GUI=True)) #pragma: no cover