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

mlange-42 / arche / 4866344964

02 May 2023 10:26PM CUT coverage: 100.0%. Remained the same
4866344964

push

github

GitHub
Better document RelationsUnchecked et al. methods (#261)

1 of 1 new or added line in 1 file covered. (100.0%)

3543 of 3543 relevant lines covered (100.0%)

1860.39 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         uint32            // 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
type Cache struct {
25
        indices       map[uint32]int                   // Mapping from filter IDs to indices in filters
26
        filters       []cacheEntry                     // The cached filters, indexed by indices
27
        getArchetypes func(f Filter) archetypePointers // Callback for getting archetypes for a new filter from the world
28
        intPool       intPool[uint32]                  // Pool for filter IDs
29
}
30

31
// newCache creates a new [Cache].
32
func newCache() Cache {
81✔
33
        return Cache{
81✔
34
                intPool: newIntPool[uint32](128),
81✔
35
                indices: map[uint32]int{},
81✔
36
                filters: []cacheEntry{},
81✔
37
        }
81✔
38
}
81✔
39

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

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

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

8✔
81
        return filter
8✔
82
}
83

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

94
// Adds an archetype.
95
//
96
// Iterates over all filters and adds the archetype to the resp. entry where the filter matches.
97
func (c *Cache) addArchetype(arch *archetype) {
1,242✔
98
        ln := len(c.filters)
1,242✔
99
        for i := 0; i < ln; i++ {
1,251✔
100
                e := &c.filters[i]
9✔
101
                if arch.Matches(e.Filter) {
13✔
102
                        e.Archetypes.Add(arch)
4✔
103
                }
4✔
104
        }
105
}
106

107
// Removes an archetype.
108
//
109
// Iterates over all filters and removes the archetype from the resp. entry where the filter matches.
110
func (c *Cache) removeArchetype(arch *archetype) {
12✔
111
        ln := len(c.filters)
12✔
112
        for i := 0; i < ln; i++ {
15✔
113
                e := &c.filters[i]
3✔
114
                if arch.Matches(e.Filter) {
4✔
115
                        e.Archetypes.Remove(arch)
1✔
116
                }
1✔
117
        }
118
}
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