Skip to content

Commit a4d1945

Browse files
committed
run 11 iterations of all benchmarks only
1 parent eeb4974 commit a4d1945

File tree

1 file changed

+73
-23
lines changed

1 file changed

+73
-23
lines changed

benchmarks/chipmunk.py

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,56 @@
1+
"""
2+
A suite of benchmarks that tests various simulation setups. Each benchmark is
3+
designed to stress Pymunk and the underlying Chipmunk2D engine in different
4+
ways.
5+
6+
They meant to measure changes from optimizations made to Pymunk and/or
7+
Chipmunk, e.g. how did performance change between Pymunk version X and Pymunk
8+
version Y. The absolute time by itself of a test does not really say that
9+
much. One test can not be compared to another test.
10+
11+
Note that running the full suite of benchmarks is very heavy and
12+
timeconsuming.
13+
14+
Below is an overview of the various benchmarks. These ones were ported over
15+
from the `box2d-optimized <https://github.com/mtsamis/box2d-optimized>_ fork
16+
of Box2D, which proposed multuple improvements to the Box2D engine. All credit
17+
to their creator(s).
18+
19+
- Falling squares: A scene with stacked squares of varying sizes falling against a ground body.
20+
- Falling circles: The same scene as above but with circles.
21+
- Tumbler: Adds new bodies in each step inside a rotating object (See Tumbler in the Box2D testbed).
22+
- Add pair: A object that moves very fast hits a big group of resting circles in a zero-gravity world.
23+
- mild n^2: Spawns a number of composite objects (tables and spaceships as found in one Box2D testbed) one on top of each other, creating a degenerate simulation. Stress test for the broad-phase.
24+
- n^2: A simpler version of the above. A high number of circles being on top of another, offset only by a small delta, creating an initial 'circle explosion' byu the solver.
25+
- Multi-fixture: A scene that creates multiple table objects with greatly varying fixture counts.
26+
- Mostly static (single body): A huge static square made from a high number of small static square fixtures with only very few dynamic bodies that exist in a diagonal corridor inside the big box.
27+
- Mostly static (multi body): The same scene as above but all the small squares are individual bodies with a single fixture.
28+
- Diagonal: A benchmark with some dynamic bodies falling through a lot of static bodies that are shaped like diagonal lines. Stress test for contact count.
29+
- Mixed static/dynamic: A casual scene with both static and dynamic bodies, polygons and circles, some movement and collisions.
30+
- Big mobile: A structure resembling Box2D's 'balanced mobile' scene but much larger. A lot of joints and bodies.
31+
- Slow explosion: A 'calm' scene with a high number of bodies moving slowly and without collisions in a zero gravity world.
32+
33+
Note that its not possible to directly compare the values to the Box2D
34+
implementation, unless the simulation state is also reviewed first to match.
35+
E.g. Pymunk (or Box2D) can be more stable or accurate, which also needs to be
36+
taken into consideration when comparing the two.
37+
38+
..
39+
It is possible more are added in the future.
40+
41+
# Higher is better tests (stability/accuracy) tests
42+
43+
- Stack boxes and see how tall until fall down
44+
- Newtons pendulum
45+
46+
# Perf tests
47+
48+
- Big body with high velocity hit group of circle in zero gravity. 1000? bodies
49+
50+
- Slow explosion
51+
52+
"""
53+
154
import argparse
255
import csv
356
import gc
@@ -15,21 +68,6 @@
1568
pymunk.pygame_util.positive_y_is_up = True
1669
except:
1770
pass
18-
"""
19-
Benchmarks
20-
21-
# Higher is better tests (stability/accuracy) tests
22-
23-
- Stack boxes and see how tall until fall down
24-
- Newtons pendulum
25-
26-
# Perf tests
27-
28-
- Big body with high velocity hit group of circle in zero gravity. 1000? bodies
29-
30-
- Slow explosion
31-
32-
"""
3371

3472

3573
class Benchmark:
@@ -568,10 +606,12 @@ def draw(self):
568606
def run(bench_cls, size, interactive):
569607
steps = 0
570608
fps = 60
571-
sim = bench_cls(size)
609+
572610
gc.collect()
573611

574-
start_time = timeit.default_timer()
612+
init_start_time = timeit.default_timer()
613+
sim = bench_cls(size)
614+
sim_start_time = timeit.default_timer()
575615

576616
if interactive:
577617
clock = pygame.time.Clock()
@@ -628,7 +668,7 @@ def run(bench_cls, size, interactive):
628668

629669
clock.tick(fps)
630670
pygame.display.set_caption(
631-
f"step {steps} fps {clock.get_fps():.2f} total {timeit.default_timer()-start_time:.2f}s"
671+
f"step {steps} fps {clock.get_fps():.2f} total {timeit.default_timer()-sim_start_time:.2f}s"
632672
)
633673

634674
sim.update(1 / fps)
@@ -645,9 +685,13 @@ def run(bench_cls, size, interactive):
645685
pygame.image.save(surface, f"{bench_cls.__name__}_{size}.png")
646686
except Exception as e:
647687
print("Could not save screenshot", e)
648-
649-
time_s = timeit.default_timer() - start_time
650-
return {"benchmark": bench_cls.__name__, "size": size, "time": time_s}
688+
end_time = timeit.default_timer()
689+
return {
690+
"benchmark": bench_cls.__name__,
691+
"size": size,
692+
"init_time": sim_start_time - init_start_time,
693+
"run_time": end_time - sim_start_time,
694+
}
651695

652696

653697
if __name__ == "__main__":
@@ -678,7 +722,9 @@ def run(bench_cls, size, interactive):
678722
args = parser.parse_args()
679723

680724
csv_output = io.StringIO()
681-
writer = csv.DictWriter(csv_output, fieldnames=["benchmark", "size", "time"])
725+
writer = csv.DictWriter(
726+
csv_output, fieldnames=["benchmark", "size", "init_time", "run_time"]
727+
)
682728
writer.writeheader()
683729
for name in args.benchmarks:
684730

@@ -690,12 +736,16 @@ def run(bench_cls, size, interactive):
690736
sizes = range(
691737
bench_cls.size_start, bench_cls.size_end + 1, bench_cls.size_inc
692738
)
739+
sizes = range(
740+
bench_cls.size_start,
741+
bench_cls.size_end + 1,
742+
(bench_cls.size_end + 1 - bench_cls.size_start) // 11,
743+
)
693744
else:
694745
sizes = [args.size]
695746
print(
696747
f"Running {bench_cls.__name__} with sizes {sizes} for {bench_cls.steps} steps."
697748
)
698-
699749
for size in sizes:
700750

701751
res = run(bench_cls, size, args.interactive)

0 commit comments

Comments
 (0)