mirror of
				https://github.com/lubuntu-team/ci-tooling.git
				synced 2025-10-31 14:04:05 +00:00 
			
		
		
		
	Initial commit of the timer_metrics module.
This commit is contained in:
		
							parent
							
								
									86f658cb55
								
							
						
					
					
						commit
						42869ace27
					
				
							
								
								
									
										0
									
								
								ci/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								ci/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										138
									
								
								ci/timer_metrics.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										138
									
								
								ci/timer_metrics.py
									
									
									
									
									
										Executable file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user