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