summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/benchmarks/MonoGame.Extended.Benchmarks.Collisions/SpaceAlgorithms.cs
blob: 7c82a3294d652da1eaa90717d6932b8e21b84534 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Engines;
using Microsoft.Xna.Framework;
using MonoGame.Extended.Benchmarks.Collisions.Utils;
using MonoGame.Extended.Collisions;
using MonoGame.Extended.Collisions.Layers;
using MonoGame.Extended.Collisions.QuadTree;

namespace MonoGame.Extended.Benchmarks.Collisions;

[SimpleJob(RunStrategy.ColdStart, launchCount:10)]
public class SpaceAlgorithms
{
    private const int COMPONENT_BOUNDARY_SIZE = 1000;

    private readonly Random _random = new ();
    private ISpaceAlgorithm _space;
    private ICollisionActor _actor;
    private RectangleF _bound;
    private List<Collider> _colliders = new();

    [Params(10, 100, 1000)]
    public int N { get; set; }

    [Params("SpatialHash", "QuadTree")]
    public string Algorithm { get; set; }


    [GlobalSetup]
    public void GlobalSetup()
    {
        var size = new Size2(COMPONENT_BOUNDARY_SIZE, COMPONENT_BOUNDARY_SIZE);
        _space = Algorithm switch
        {
            "SpatialHash" => new SpatialHash(new Size2(32, 32)),
            "QuadTree" => new QuadTreeSpace(new RectangleF(Point2.Zero, size)),
            _ => _space
        };
        for (int i = 0; i < N; i++)
        {

            var rect = GetRandomRectangleF();
            var actor = new Collider(rect);
            _colliders.Add(actor);
            _space.Insert(actor);
        }
    }

    [GlobalCleanup]
    public void GlobalCleanup()
    {
        foreach (var collider in _colliders)
            _space.Remove(collider);
        _colliders.Clear();
    }

    [GlobalSetup(Targets = new[] { nameof(Insert), nameof(Remove) })]
    public void ActorGlobalSetup()
    {
        GlobalSetup();
        var rect = GetRandomRectangleF();
        _actor = new Collider(rect);
    }

    [Benchmark]
    public void Insert()
    {
        _space.Insert(_actor);
    }

    [Benchmark]
    public void Remove()
    {
        _space.Remove(_actor);
    }

    [Benchmark]
    public void Reset()
    {
        _space.Reset();
    }

    [GlobalSetup(Target = nameof(Query))]
    public void QueryGlobalSetup()
    {
        GlobalSetup();
        _bound = GetRandomRectangleF();
    }

    private RectangleF GetRandomRectangleF()
    {
        return new RectangleF(
            _random.Next(COMPONENT_BOUNDARY_SIZE),
            _random.Next(COMPONENT_BOUNDARY_SIZE),
            _random.Next(32, 128),
            _random.Next(32, 128));
    }

    [Benchmark]
    public List<ICollisionActor> Query()
    {
        return _space.Query(_bound).ToList();
    }
}