Skip to content

Commit

Permalink
re-arrange struct fields to save memory
Browse files Browse the repository at this point in the history
  • Loading branch information
mlange-42 committed Apr 18, 2024
1 parent b79689b commit 062002a
Show file tree
Hide file tree
Showing 12 changed files with 50 additions and 46 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

* Adds a showcase chapter "Made with Arche" to the documentation page (#411)

### Performance

* Re-arrange struct fields to save memory in a few places (#413)

### First-time contributors

* [delaneyj](https://github.com/delaneyj)
Expand Down
20 changes: 10 additions & 10 deletions ecs/archetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ var layoutSize uint32 = uint32(unsafe.Sizeof(layout{}))

// Helper for accessing data from an archetype
type archetypeAccess struct {
Mask Mask // Archetype's mask
basePointer unsafe.Pointer // Pointer to the first component column layout.
entityPointer unsafe.Pointer // Pointer to the entity storage
Mask Mask // Archetype's mask
RelationTarget Entity // Target entity of the archetype (if it has a relation component)
RelationComponent ID // Relation component of the archetype
HasRelationComponent bool // Whether the archetype has a relation
Expand Down Expand Up @@ -64,19 +64,19 @@ func (l *layout) Get(index uint32) unsafe.Pointer {

// archetype represents an ECS archetype
type archetype struct {
archetypeAccess // Access helper, passed to queries.
*archetypeData
node *archNode // Node in the archetype graph.
len uint32 // Current number of entities
cap uint32 // Current capacity
node *archNode
archetypeAccess
len uint32
cap uint32
}

type archetypeData struct {
layouts []layout // Column layouts by ID.
indices idMap[uint32] // Mapping from IDs to buffer indices.
buffers []reflect.Value // Reflection arrays containing component data.
entityBuffer reflect.Value // Reflection array containing entity data.
index int32 // Index of the archetype in the world.
entityBuffer reflect.Value
layouts []layout
buffers []reflect.Value
indices idMap[uint32]
index int32
}

// Init initializes an archetype
Expand Down
16 changes: 8 additions & 8 deletions ecs/archetype_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ type archNode struct {
}

type nodeData struct {
Ids []ID // List of component IDs
Types []reflect.Type // Component type per column
TransitionAdd idMap[*archNode] // Mapping from component ID to add to the resulting archetype
TransitionRemove idMap[*archNode] // Mapping from component ID to remove to the resulting archetype
archetype *archetype // The single archetype for nodes without entity relation
archetypes pagedSlice[archetype] // Storage for archetypes in nodes with entity relation
archetypeData pagedSlice[archetypeData]
archetypeMap map[Entity]*archetype // Mapping from relation targets to archetypes
zeroPointer unsafe.Pointer // Points to zeroValue for fast access
Types []reflect.Type // Component type per column
Ids []ID // List of component IDs
freeIndices []int32 // Indices of free/inactive archetypes
zeroValue []byte // Used as source for setting storage to zero
zeroPointer unsafe.Pointer // Points to zeroValue for fast access
capacityIncrement uint32 // Capacity increment
archetypes pagedSlice[archetype] // Storage for archetypes in nodes with entity relation
archetypeData pagedSlice[archetypeData]
TransitionAdd idMap[*archNode] // Mapping from component ID to add to the resulting archetype
TransitionRemove idMap[*archNode] // Mapping from component ID to remove to the resulting archetype
capacityIncrement uint32 // Capacity increment
}

// Creates a new archNode
Expand Down
4 changes: 2 additions & 2 deletions ecs/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package ecs

// Cache entry for a [Filter].
type cacheEntry struct {
ID uint32 // Filter ID.
Filter Filter // The underlying filter.
Archetypes pointers[archetype] // Nodes matching the filter.
Indices map[*archetype]int // Map of archetype indices for removal.
Archetypes pointers[archetype] // Nodes matching the filter.
ID uint32 // Filter ID.
}

// Cache provides [Filter] caching to speed up queries.
Expand Down
6 changes: 3 additions & 3 deletions ecs/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ import "github.com/mlange-42/arche/ecs/event"
// For batch methods that return a [Query], events are fired after the [Query] is closed (or fully iterated).
// This allows the [World] to be in an unlocked state, and notifies after potential entity initialization.
type EntityEvent struct {
Entity Entity // The entity that was changed.
Added, Removed Mask // Masks indicating changed components (additions and removals).
AddedIDs, RemovedIDs []ID // Components added and removed. DO NOT MODIFY! Get the current components with [World.Ids].
OldRelation, NewRelation *ID // Old and new relation component ID. No relation is indicated by nil.
AddedIDs, RemovedIDs []ID // Components added and removed. DO NOT MODIFY! Get the current components with [World.Ids].
Added, Removed Mask // Masks indicating changed components (additions and removals).
Entity Entity // The entity that was changed.
OldTarget Entity // Old relation target entity. Get the new target with [World.Relations] and [Relations.Get].
EventTypes event.Subscription // Bit mask of event types. See [event.Subscription].
}
Expand Down
4 changes: 2 additions & 2 deletions ecs/id_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ const (
//
// The range of keys is limited from 0 to [MaskTotalBits]-1.
type idMap[T any] struct {
zeroValue T
chunks [][]T
used Mask
chunkUsed []uint8
zeroValue T
used Mask
}

// newIDMap creates a new idMap
Expand Down
4 changes: 2 additions & 2 deletions ecs/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ func (p *entityPool) Available() int {

// bitPool is an entityPool implementation using implicit linked lists.
type bitPool struct {
length uint16
bits [MaskTotalBits]uint8
next uint8
length uint16
available uint8
}

Expand Down Expand Up @@ -143,8 +143,8 @@ func (p *bitPool) Reset() {
// entityPool is an implementation using implicit linked lists.
// Implements https://skypjack.github.io/2019-05-06-ecs-baf-part-3/
type intPool[T number] struct {
pool []T
next T
pool []T
available uint32
capacityIncrement uint32
}
Expand Down
8 changes: 4 additions & 4 deletions ecs/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import (
// [github.com/mlange-42/arche/generic.Query2], etc.
// For advanced filtering, see package [github.com/mlange-42/arche/filter].
type Query struct {
filter Filter // The filter used by the query.
archetypes []*archetype // The query's filtered archetypes.
nodeArchetypes archetypes // The query's archetypes of the current node.
nodes []*archNode // The query's nodes.
world *World // The [World].
filter Filter // The filter used by the query.
access *archetypeAccess // Access helper for the archetype currently being iterated.
archetype *archetype // The archetype currently being iterated.
world *World // The [World].
nodes []*archNode // The query's nodes.
archetypes []*archetype // The query's filtered archetypes.
entityIndex uint32 // Iteration index of the current [Entity] current archetype.
entityIndexMax uint32 // Maximum entity index in the current archetype.
archIndex int32 // Iteration index of the current archetype.
Expand Down
2 changes: 1 addition & 1 deletion ecs/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
type componentRegistry struct {
Components map[reflect.Type]uint8
Types []reflect.Type
IDs []uint8
Used Mask
IsRelation Mask
IDs []uint8
}

// newComponentRegistry creates a new ComponentRegistry.
Expand Down
2 changes: 1 addition & 1 deletion ecs/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
//
// Access it using [World.Resources].
type Resources struct {
registry componentRegistry
resources []any
registry componentRegistry
}

// newResources creates a new Resources manager.
Expand Down
20 changes: 10 additions & 10 deletions ecs/world.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ import (
// For more advanced functionality, see [World.Relations], [World.Resources],
// [World.Batch], [World.Cache] and [Builder].
type World struct {
config Config // World configuration.
listener Listener // EntityEvent listener.
resources Resources // World resources.
nodePointers []*archNode // Helper list of all node pointers for queries.
entities []entityIndex // Mapping from entities to archetype and index.
targetEntities bitSet // Whether entities are potential relation targets. Used for archetype cleanup.
entityPool entityPool // Pool for entities.
archetypes pagedSlice[archetype] // Archetypes that have no relations components.
archetypeData pagedSlice[archetypeData] // Storage for the actual archetype data (components).
relationNodes []*archNode // Archetype nodes that have an entity relation.
filterCache Cache // Cache for registered filters.
nodes pagedSlice[archNode] // The archetype graph.
archetypeData pagedSlice[archetypeData] // Storage for the actual archetype data (components).
nodeData pagedSlice[nodeData] // The archetype graph's data.
nodePointers []*archNode // Helper list of all node pointers for queries.
relationNodes []*archNode // Archetype nodes that have an entity relation.
locks lockMask // World locks.
archetypes pagedSlice[archetype] // Archetypes that have no relations components.
entityPool entityPool // Pool for entities.
stats stats.World // Cached world statistics.
resources Resources // World resources.
registry componentRegistry // Component registry.
filterCache Cache // Cache for registered filters.
stats stats.World // Cached world statistics
locks lockMask // World locks.
config Config // World configuration.
}

// NewWorld creates a new [World] from an optional [Config].
Expand Down
6 changes: 3 additions & 3 deletions ecs/world_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -1129,9 +1129,9 @@ func (w *World) notifyQuery(batchArch *batchArchetypes) {
}

event := EntityEvent{
Entity{}, arch.Mask, Mask{}, batchArch.Added, batchArch.Removed,
nil, newRel,
Entity{}, 0,
Entity: Entity{}, Added: arch.Mask, Removed: Mask{}, AddedIDs: batchArch.Added, RemovedIDs: batchArch.Removed,
OldRelation: nil, NewRelation: newRel,
OldTarget: Entity{}, EventTypes: 0,
}

oldArch := batchArch.OldArchetype[i]
Expand Down

0 comments on commit 062002a

Please sign in to comment.