From 45e5fc7e3b6913eaba04ed4ed9502bfcb416de46 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Wed, 12 Jun 2024 20:01:30 +0200 Subject: [PATCH] tried arche ecs: utter fail, needs 4.3 the time --- go.mod | 1 + go.sum | 2 + various-tests/README.md | 1 + various-tests/perf-ecs/go.mod | 5 ++ various-tests/perf-ecs/go.sum | 2 + various-tests/perf-ecs/main.go | 145 +++++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+) create mode 100644 various-tests/perf-ecs/go.mod create mode 100644 various-tests/perf-ecs/go.sum create mode 100644 various-tests/perf-ecs/main.go diff --git a/go.mod b/go.mod index 7fb825f..3e54e3a 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/ebitenui/ebitenui v0.5.8-0.20240608175527-424f62327b21 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/jezek/xgb v1.1.1 // indirect + github.com/mlange-42/arche v0.13.0 // indirect github.com/tinne26/etxt v0.0.8 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/sync v0.7.0 // indirect diff --git a/go.sum b/go.sum index 70129b4..46f6477 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/hajimehoshi/ebiten/v2 v2.7.4 h1:X+heODRQ3Ie9F9QFjm24gEZqQd5FSfR9XuT2X github.com/hajimehoshi/ebiten/v2 v2.7.4/go.mod h1:H2pHVgq29rfm5yeQ7jzWOM3VHsjo7/AyucODNLOhsVY= github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= +github.com/mlange-42/arche v0.13.0 h1:ef0fu9qC2KIr8wIlVs+CgeQ5CSUJ8A1Hut6nXYdf+xk= +github.com/mlange-42/arche v0.13.0/go.mod h1:bFktKnvGDj2kP01xar79z0hKwGHdnoaEZR8HWmJkIyU= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/tinne26/etxt v0.0.8 h1:rjb58jkMkapRGLmhBMWnT76E/nMTXC5P1Q956BRZkoc= diff --git a/various-tests/README.md b/various-tests/README.md index c5490af..bf49ecf 100644 --- a/various-tests/README.md +++ b/various-tests/README.md @@ -9,3 +9,4 @@ Running with 1500x1500 grid 5k times | perf-2dim-pointers-array | same as above but array of neighbors instead of slice | 00:02:40 | | perf-2dim-pointers-all-array | use arrays for everything, static 1500x1500 | infinite, aborted | | perf-1dim | use 1d grid of bools, access using y*x, no further tuning | 00:03:24 | +| perf-ecs | use arche ecs, unusable | 00:14:51 | diff --git a/various-tests/perf-ecs/go.mod b/various-tests/perf-ecs/go.mod new file mode 100644 index 0000000..82fd6e7 --- /dev/null +++ b/various-tests/perf-ecs/go.mod @@ -0,0 +1,5 @@ +module perf + +go 1.22 + +require github.com/mlange-42/arche v0.13.0 // indirect diff --git a/various-tests/perf-ecs/go.sum b/various-tests/perf-ecs/go.sum new file mode 100644 index 0000000..8e955c4 --- /dev/null +++ b/various-tests/perf-ecs/go.sum @@ -0,0 +1,2 @@ +github.com/mlange-42/arche v0.13.0 h1:ef0fu9qC2KIr8wIlVs+CgeQ5CSUJ8A1Hut6nXYdf+xk= +github.com/mlange-42/arche v0.13.0/go.mod h1:bFktKnvGDj2kP01xar79z0hKwGHdnoaEZR8HWmJkIyU= diff --git a/various-tests/perf-ecs/main.go b/various-tests/perf-ecs/main.go new file mode 100644 index 0000000..ced59ba --- /dev/null +++ b/various-tests/perf-ecs/main.go @@ -0,0 +1,145 @@ +package main + +import ( + "fmt" + "log" + "math/rand" + "os" + "runtime/pprof" + + "github.com/mlange-42/arche/ecs" + "github.com/mlange-42/arche/generic" +) + +const ( + max int = 1500 + loops int = 5000 + density int = 8 + debug bool = false +) + +// components +type Pos struct { + X, Y, GridX, GridY int +} + +type Cell struct { + State bool + Neighbors [8]ecs.Entity +} + +type ECS struct { + World *ecs.World + Filter *generic.Filter2[Pos, Cell] + Map *generic.Map2[Pos, Cell] +} + +func (cell *Cell) NeighborCount(ECS *ECS) int { + sum := 0 + + for _, neighbor := range cell.Neighbors { + if ECS.World.Alive(neighbor) { + _, cel := ECS.Map.Get(neighbor) + if cel.State { + sum++ + } + } + } + + return sum +} + +func Loop(ECS *ECS) { + c := 0 + + for i := 0; i < loops; i++ { + query := ECS.Filter.Query(ECS.World) + + for query.Next() { + _, cel := query.Get() + if cel.State && cel.NeighborCount(ECS) > 1 { + c = 1 + } + } + } + + if c > 1 { + c = 0 + } +} + +func SetupWorld() *ECS { + world := ecs.NewWorld() + + builder := generic.NewMap2[Pos, Cell](&world) + + // we need a temporary grid in order to find out neighbors + grid := [max][max]ecs.Entity{} + + // setup entities + for y := 0; y < max; y++ { + for x := 0; x < max; x++ { + e := builder.New() + pos, cell := builder.Get(e) + pos.X = x + pos.Y = y // pos.GridX = x*cellsize + + cell.State = false + if rand.Intn(density) == 1 { + cell.State = true + } + + // store to tmp grid + grid[y][x] = e + } + } + + // global filter + filter := generic.NewFilter2[Pos, Cell]() + + query := filter.Query(&world) + + for query.Next() { + pos, cel := query.Get() + + n := 0 + for x := -1; x < 2; x++ { + for y := -1; y < 2; y++ { + XX := pos.X + x + YY := pos.Y + y + if XX < 0 || XX >= max || YY < 0 || YY >= max { + continue + } + + if pos.X != XX || pos.Y != YY { + cel.Neighbors[n] = grid[XX][YY] + n++ + } + } + } + } + + return &ECS{World: &world, Filter: filter, Map: &builder} +} + +func main() { + // enable cpu profiling. Do NOT use q to stop the game but + // close the window to get a profile + fd, err := os.Create("cpu.profile") + if err != nil { + log.Fatal(err) + } + defer fd.Close() + + pprof.StartCPUProfile(fd) + defer pprof.StopCPUProfile() + + // init + fmt.Print("Setup ... ") + ECS := SetupWorld() + fmt.Println("done") + fmt.Println(ECS.World.Stats()) + + // main loop + Loop(ECS) +}