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