parent
86f658cb55
commit
42869ace27
@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2020 Simon Quigley <tsimonq2@lubuntu.me>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import time
|
||||
import tabulate
|
||||
from tabulate import tabulate
|
||||
|
||||
tabulate.PRESERVE_WHITESPACE = True
|
||||
|
||||
|
||||
class TimerMetrics:
|
||||
"""Timer Metrics
|
||||
|
||||
This leverages the timer module to provide a lightweight set of timer
|
||||
utilities, to keep track of how long specific sub-processes in a Python
|
||||
program are taking.
|
||||
|
||||
Data structure:
|
||||
{
|
||||
"Timer name": {
|
||||
"running": True,
|
||||
"start_time": 123.4,
|
||||
"total_time": 0.0
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Store the data in a dictionary
|
||||
self.data = {}
|
||||
|
||||
def start(self, name):
|
||||
"""Start a timer with a given name
|
||||
|
||||
This records the current time and adds a new entry. If the entry
|
||||
already exists and the timer is not running, start it up again. If
|
||||
the entry exists and the timer is already running, do nothing.
|
||||
"""
|
||||
|
||||
# Get a timer value ASAP
|
||||
t_val = time.perf_counter()
|
||||
|
||||
# If it isn't already there, create an entry
|
||||
if name not in self.data:
|
||||
# Initialize the entry
|
||||
self.data[name] = {}
|
||||
|
||||
# Make sure it is running
|
||||
self.data[name]["running"] = True
|
||||
|
||||
# Put our times in there
|
||||
self.data[name]["start_time"] = t_val
|
||||
self.data[name]["total_time"] = 0.0
|
||||
|
||||
# If it is there, only act if it's running
|
||||
elif self.data[name]["running"] == False:
|
||||
# Now we're running
|
||||
self.data[name]["running"] = True
|
||||
|
||||
# Change our start time as well
|
||||
self.data[name]["start_time"] = t_val
|
||||
|
||||
def stop(self, name):
|
||||
"""Stop a timer with the given name
|
||||
|
||||
This stops the timer if it is running. If there is no such timer
|
||||
currently running, throw an error. If the timer exists and is running,
|
||||
stop it and update total_time. If the timer exists but isn't running,
|
||||
do nothing.
|
||||
"""
|
||||
|
||||
# Get a timer value ASAP
|
||||
t_val = time.perf_counter()
|
||||
|
||||
# Raise an error if the timer doesn't exist
|
||||
if name not in self.data:
|
||||
assert ValueError("Timer " + name + " not found")
|
||||
|
||||
# If the timer is running, update total_time and stop it
|
||||
if self.data[name]["running"] == True:
|
||||
# Stop the timer
|
||||
self.data[name]["running"] = False
|
||||
|
||||
# Get the current time and add it to any existing time, which
|
||||
# may indeed exist
|
||||
cur_time = t_val - self.data[name]["start_time"]
|
||||
self.data[name]["total_time"] += cur_time
|
||||
|
||||
def display(self):
|
||||
"""Print a pretty(-ish) table with all of the data in it"""
|
||||
|
||||
# Initialize the dict for the table we're going to render
|
||||
# The dict keys are the headers
|
||||
table = {}
|
||||
|
||||
# Simplify the data with just the times and the timer labels
|
||||
pretty = {}
|
||||
for item in self.data:
|
||||
pretty[item] = self.data[item]["total_time"]
|
||||
|
||||
# Sort the data into descending order and then put them into two lists
|
||||
# Keys have one list and values have another
|
||||
s_pretty = {k: v for k, v in sorted(pretty.items(), key=lambda item: item[1], reverse=True)}
|
||||
table["Timer"] = list(s_pretty.keys())
|
||||
table["Seconds"] = list(s_pretty.values())
|
||||
|
||||
# Get a total second count
|
||||
total_secs = 0.0
|
||||
for i in range(len(table["Seconds"])):
|
||||
total_secs += table["Seconds"][i]
|
||||
|
||||
# Add the totals to the table
|
||||
table["Timer"].append("Total Time")
|
||||
table["Seconds"].append(total_secs)
|
||||
|
||||
# Get percentages in its own column
|
||||
table["% of total"] = []
|
||||
for i in range(len(table["Seconds"])):
|
||||
percent = ( table["Seconds"][i] / total_secs ) * 100.0
|
||||
# Round to the nearest hundredth and add a %
|
||||
table["% of total"].append(str(round(percent, 2)) + "%")
|
||||
|
||||
# Show the pretty table
|
||||
print(tabulate(table, headers="keys", tablefmt="grid"))
|
Loading…
Reference in new issue