Performance Statistics

Arcade includes performance monitoring tools to help you optimize your game. This example demonstrates the following performance api features:
If you do not want to display graphs in your game window, you can use
arcade.print_timings()
to print out the count and average time for
all dispatched events with the function. The output looks like this:
Event Count Average Time
-------------- ----- ------------
on_activate 1 0.0000
on_resize 1 0.0000
on_show 1 0.0000
on_update 59 0.0000
on_expose 1 0.0000
on_draw 59 0.0021
on_mouse_enter 1 0.0000
on_mouse_motion 100 0.0000
See Performance Information for more information about the performance api.
performance_statistics.py
1"""
2Performance Statistic Display Example
3
4This example demonstrates how to use a few performance profiling tools
5built into Arcade:
6
7* arcade.enable_timings
8* arcade.PerfGraph
9* arcade.get_fps
10* arcade.print_timings
11* arcade.clear_timings
12
13A large number of sprites bounce around the screen to produce load. You
14can adjust the number of sprites by changing the COIN_COUNT constant.
15
16Artwork from https://kenney.nl
17
18If Python and Arcade are installed, this example can be run from the
19command line with:
20python -m arcade.examples.performance_statistics
21"""
22from __future__ import annotations
23import random
24
25import arcade
26
27# --- Constants ---
28SPRITE_SCALING_COIN = 0.25
29SPRITE_NATIVE_SIZE = 128
30SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING_COIN)
31
32WINDOW_WIDTH = 1280
33WINDOW_HEIGHT = 720
34WINDOW_TITLE = "Performance Statistics Display Example"
35
36# Size of performance graphs and distance between them
37GRAPH_WIDTH = 200
38GRAPH_HEIGHT = 120
39GRAPH_MARGIN = 5
40
41COIN_COUNT = 1500
42
43# Turn on tracking for the number of event handler
44# calls and the average execution time of each type.
45arcade.enable_timings()
46
47
48class Coin(arcade.BasicSprite):
49 """ Our coin sprite class """
50 def __init__(self, texture: arcade.Texture, scale: float):
51 super().__init__(texture, scale=scale)
52 # Add a velocity to the coin
53 self.change_x = 0
54 self.change_y = 0
55
56 def update(self, delta_time: float = 1/60):
57 """ Update the sprite. """
58 # Setting the position is faster than setting x & y individually
59 self.position = (
60 self.position[0] + self.change_x,
61 self.position[1] + self.change_y
62 )
63
64 # Bounce the coin on the edge of the window
65 if self.position[0] < 0:
66 self.change_x *= -1
67 elif self.position[0] > WINDOW_WIDTH:
68 self.change_x *= -1
69 if self.position[1] < 0:
70 self.change_y *= -1
71 elif self.position[1] > WINDOW_HEIGHT:
72 self.change_y *= -1
73
74
75class GameView(arcade.View):
76 """ Our custom Window Class"""
77
78 def __init__(self):
79 """ Initializer """
80 # Call the parent class initializer
81 super().__init__()
82
83 # Variables to hold game objects and performance info
84 self.coin_list: arcade.SpriteList | None = None
85 self.perf_graph_list: arcade.SpriteList | None = None
86 self.fps_text: arcade.Text | None = None
87 self.frame_count: int = 0 # for tracking the reset interval
88
89 self.coin_texture = arcade.load_texture(":resources:images/items/coinGold.png")
90 self.background_color = arcade.color.AMAZON
91
92 def add_coins(self, amount):
93
94 # Create the coins
95 for i in range(amount):
96 # Create the coin instance
97 # Coin image from kenney.nl
98 coin = Coin(self.coin_texture, scale=SPRITE_SCALING_COIN)
99
100 # Position the coin
101 coin.position = (
102 random.randrange(SPRITE_SIZE, WINDOW_WIDTH - SPRITE_SIZE),
103 random.randrange(SPRITE_SIZE, WINDOW_HEIGHT - SPRITE_SIZE)
104 )
105
106 coin.change_x = random.randrange(-3, 4)
107 coin.change_y = random.randrange(-3, 4)
108
109 # Add the coin to the lists
110 self.coin_list.append(coin)
111
112 def setup(self):
113 """ Set up the game and initialize the variables. """
114
115 # Sprite lists
116 self.coin_list = arcade.SpriteList(use_spatial_hash=False)
117
118 # Create some coins
119 self.add_coins(COIN_COUNT)
120
121 # Create a sprite list to put the performance graphs into
122 self.perf_graph_list = arcade.SpriteList()
123
124 # Calculate position helpers for the row of 3 performance graphs
125 row_y = self.height - GRAPH_HEIGHT / 2
126 starting_x = GRAPH_WIDTH / 2
127 step_x = GRAPH_WIDTH + GRAPH_MARGIN
128
129 # Create the FPS performance graph
130 graph = arcade.PerfGraph(GRAPH_WIDTH, GRAPH_HEIGHT, graph_data="FPS")
131 graph.position = starting_x, row_y
132 self.perf_graph_list.append(graph)
133
134 # Create the on_update graph
135 graph = arcade.PerfGraph(GRAPH_WIDTH, GRAPH_HEIGHT, graph_data="on_update")
136 graph.position = starting_x + step_x, row_y
137 self.perf_graph_list.append(graph)
138
139 # Create the on_draw graph
140 graph = arcade.PerfGraph(GRAPH_WIDTH, GRAPH_HEIGHT, graph_data="on_draw")
141 graph.position = starting_x + step_x * 2, row_y
142 self.perf_graph_list.append(graph)
143
144 # Create a Text object to show the current FPS
145 self.fps_text = arcade.Text(
146 f"FPS: {arcade.get_fps(60):5.1f}",
147 10, 10, arcade.color.BLACK, 22
148 )
149
150 def on_draw(self):
151 """ Draw everything """
152
153 # Clear the screen
154 self.clear()
155
156 # Draw all the coin sprites
157 self.coin_list.draw()
158
159 # Draw the graphs
160 self.perf_graph_list.draw()
161
162 # Get & draw the FPS for the last 60 frames
163 if arcade.timings_enabled():
164 self.fps_text.value = f"FPS: {arcade.get_fps(60):5.1f}"
165 self.fps_text.draw()
166
167 def on_update(self, delta_time):
168 """ Update method """
169 self.frame_count += 1
170
171 # Print and clear timings every 60 frames
172 if self.frame_count % 60 == 0:
173 arcade.print_timings()
174 arcade.clear_timings()
175
176 # Move the coins
177 self.coin_list.update()
178
179 def on_key_press(self, symbol: int, modifiers: int):
180 if symbol == arcade.key.SPACE:
181 if arcade.timings_enabled():
182 arcade.disable_timings()
183 else:
184 arcade.enable_timings()
185
186
187def main():
188 """ Main function """
189 # Create a window class. This is what actually shows up on screen
190 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
191
192 # Create and setup the GameView
193 game = GameView()
194 game.setup()
195
196 # Show GameView on screen
197 window.show_view(game)
198
199 # Start the arcade game loop
200 arcade.run()
201
202if __name__ == "__main__":
203 main()