59 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			59 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
Helper class to track length of time taken for each frame and draw a graph when application exits.
 | 
						|
Also able to add events at arbitrary times across the graph.
 | 
						|
"""
 | 
						|
import time
 | 
						|
import matplotlib.pyplot as plt
 | 
						|
import statistics
 | 
						|
 | 
						|
 | 
						|
class FrametimePlotter:
 | 
						|
    EVENT_POINT_Y = -0.05
 | 
						|
    EVENT_MSG_Y = -0.045
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        self.times = []
 | 
						|
        self.events = []
 | 
						|
        self.start = time.perf_counter()
 | 
						|
 | 
						|
    def add_event(self, event_msg):
 | 
						|
        self.events.append((len(self.times), event_msg))
 | 
						|
 | 
						|
    def end_frame(self, time_delta):
 | 
						|
        self.times.append(time_delta)
 | 
						|
 | 
						|
    def _show_stats(self):
 | 
						|
        end = time.perf_counter()
 | 
						|
        print("Min   : {:.5f}".format(min(self.times)))
 | 
						|
        print("Max   : {:.5f}".format(max(self.times)))
 | 
						|
        print("Avg   : {:.5f}".format(statistics.mean(self.times)))
 | 
						|
        print("Median: {:.5f}".format(statistics.median(self.times)))
 | 
						|
        try:
 | 
						|
            print("Mode  : {:.5f}".format(statistics.mode(self.times)))
 | 
						|
        except statistics.StatisticsError as e:
 | 
						|
            print("Mode  : {}".format(e))
 | 
						|
        print("StdDev: {:.5f}".format(statistics.stdev(self.times)))
 | 
						|
        frame_count = len(self.times)
 | 
						|
        elapsed_time = end - self.start
 | 
						|
        print("Frame count: {}".format(frame_count))
 | 
						|
        print("Elapsed time: {:.5f}".format(elapsed_time))
 | 
						|
        print("FPS: {:.5f}".format(frame_count / elapsed_time))
 | 
						|
 | 
						|
    def show(self):
 | 
						|
        if len(self.times) <= 1:
 | 
						|
            return
 | 
						|
        self._show_stats()
 | 
						|
        frame_idxs = range(0, len(self.times))
 | 
						|
        event_idxs = [e[0] for e in self.events]
 | 
						|
        event_point_y = [self.EVENT_POINT_Y] * len(self.events)
 | 
						|
        plt.figure("Frame durations", figsize=(8, 6))
 | 
						|
        plt.plot(frame_idxs, self.times, event_idxs, event_point_y, "k|")
 | 
						|
        plt.xlabel("frames")
 | 
						|
        plt.ylabel("frame duration")
 | 
						|
        plt.ylim(self.EVENT_POINT_Y - 0.005, 0.5)
 | 
						|
        plt.tight_layout()
 | 
						|
        for frame_idx, msg in self.events:
 | 
						|
            plt.text(frame_idx, self.EVENT_MSG_Y, msg, horizontalalignment="center", verticalalignment="bottom",
 | 
						|
                     size="smaller", rotation="vertical")
 | 
						|
        plt.show()
 |