• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / arche / 4725747591

17 Apr 2023 08:58PM CUT coverage: 100.0%. Remained the same
4725747591

push

github

GitHub
Add parallel simulations example (#223)

2729 of 2729 relevant lines covered (100.0%)

4272.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/ecs/cache.go
1
package ecs
2

3
// Cache entry for a [Filter].
4
type cacheEntry struct {
5
        ID         ID                // Filter ID.
6
        Filter     Filter            // The underlying filter.
7
        Archetypes archetypePointers // Archetypes matching the filter.
8
}
9

10
// Cache provides [Filter] caching to speed up queries.
11
//
12
// Access it using [World.Cache].
13
//
14
// For registered filters, the relevant archetypes are tracked internally,
15
// so that there are no mask checks required during iteration.
16
// This is particularly helpful to avoid query iteration slowdown by a very high number of archetypes.
17
// If the number of archetypes exceeds approx. 50-100, uncached filters experience a slowdown.
18
// The relative slowdown increases with lower numbers of entities queried (below a few thousand).
19
// Cached filters avoid this slowdown.
20
//
21
// Further, cached filters should be used for complex queries built with package [github.com/mlange-42/arche/filter].
22
//
23
// The overhead of tracking cached filters internally is very low, as updates are required only when new archetypes are created.
24
// The number of cached filters is limited to [MaskTotalBits].
25
type Cache struct {
26
        indices       idMap[int]                       // Mapping from filter IDs to indices in filters
27
        filters       []cacheEntry                     // The cached filters, indexed by indices
28
        getArchetypes func(f Filter) archetypePointers // Callback for getting archetypes for a new filter from the world
29
        bitPool       bitPool                          // Pool for filter IDs
30
}
31

32
// newCache creates a new [Cache].
33
func newCache() Cache {
77✔
34
        return Cache{
77✔
35
                bitPool: bitPool{},
77✔
36
                indices: newIDMap[int](),
77✔
37
                filters: []cacheEntry{},
77✔
38
        }
77✔
39
}
77✔
40

41
// Register a [Filter].
42
//
43
// Use the returned [CachedFilter] to construct queries:
44
//
45
//        filter := All(posID, velID)
46
//        cached := world.Cache().Register(&filter)
47
//        query := world.Query(&cached)
48
func (c *Cache) Register(f Filter) CachedFilter {
9✔
49
        if _, ok := f.(*CachedFilter); ok {
10✔
50
                panic("filter is already cached")
1✔
51
        }
52
        id := c.bitPool.Get()
8✔
53
        c.filters = append(c.filters,
8✔
54
                cacheEntry{
8✔
55
                        ID:         id,
8✔
56
                        Filter:     f,
8✔
57
                        Archetypes: c.getArchetypes(f),
8✔
58
                })
8✔
59
        c.indices.Set(id, len(c.filters)-1)
8✔
60
        return CachedFilter{f, id}
8✔
61
}
62

63
// Unregister a filter.
64
//
65
// Returns the original filter.
66
func (c *Cache) Unregister(f *CachedFilter) Filter {
3✔
67
        idx, ok := c.indices.Get(f.id)
3✔
68
        if !ok {
4✔
69
                panic("no filter for id found to unregister")
1✔
70
        }
71
        filter := c.filters[idx].Filter
2✔
72
        c.indices.Remove(f.id)
2✔
73

2✔
74
        last := len(c.filters) - 1
2✔
75
        if idx != last {
3✔
76
                c.filters[idx], c.filters[last] = c.filters[last], c.filters[idx]
1✔
77
                c.indices.Set(c.filters[idx].ID, idx)
1✔
78
        }
1✔
79
        c.filters[last] = cacheEntry{}
2✔
80
        c.filters = c.filters[:last]
2✔
81

2✔
82
        return filter
2✔
83
}
84

85
// Returns the [cacheEntry] for the given filter.
86
//
87
// Panics if there is no entry for the filter's ID.
88
func (c *Cache) get(f *CachedFilter) *cacheEntry {
12✔
89
        if idx, ok := c.indices.Get(f.id); ok {
23✔
90
                return &c.filters[idx]
11✔
91
        }
11✔
92
        panic("no filter for id found")
1✔
93
}
94

95
// Adds an archetype.
96
//
97
// Iterates over all filters and adds the archetype to the resp. entry where the filter matches.
98
func (c *Cache) addArchetype(arch *archetype) {
1,179✔
99
        ln := len(c.filters)
1,179✔
100
        for i := 0; i < ln; i++ {
1,185✔
101
                e := &c.filters[i]
6✔
102
                if e.Filter.Matches(arch.Mask) {
9✔
103
                        e.Archetypes.Add(arch)
3✔
104
                }
3✔
105
        }
106
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc