Performance Statistics

../../_images/performance_statistics1.png

Arcade includes performance monitoring tools to help you optimize your game. This example demonstrates the following performance api features:

  • arcade.enable_timings()

  • arcade.PerfGraph

  • arcade.get_fps()

  • arcade.print_timings()

  • arcade.clear_timings()

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
 23from typing import Optional
 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
 32SCREEN_WIDTH = 800
 33SCREEN_HEIGHT = 600
 34SCREEN_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):
 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] > SCREEN_WIDTH:
 68            self.change_x *= -1
 69        if self.position[1] < 0:
 70            self.change_y *= -1
 71        elif self.position[1] > SCREEN_HEIGHT:
 72            self.change_y *= -1
 73
 74
 75class MyGame(arcade.Window):
 76    """ Our custom Window Class"""
 77
 78    def __init__(self):
 79        """ Initializer """
 80        # Call the parent class initializer
 81        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
 82
 83        # Variables to hold game objects and performance info
 84        self.coin_list: Optional[arcade.SpriteList] = None
 85        self.perf_graph_list: Optional[arcade.SpriteList] = None
 86        self.fps_text: Optional[arcade.Text] = 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, SCREEN_WIDTH - SPRITE_SIZE),
103                random.randrange(SPRITE_SIZE, SCREEN_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    window = MyGame()
190    window.setup()
191    arcade.run()
192
193
194if __name__ == "__main__":
195    main()