Skip to content

Commit

Permalink
Merge pull request #7 from s0rg/feature/benchmarks
Browse files Browse the repository at this point in the history
benchmarks + minor optimizations
  • Loading branch information
s0rg authored Jul 31, 2023
2 parents 1d19ea7 + 6d0e73c commit b46676b
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ issues:
linters:
- funlen
- cyclop
- gosec
- unparam
- path: path.go
text: "appendAssign"
linters:
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ test: vet
test-cover: test
@- go tool cover -func="$(COP)"


bench:
@- go test -count 1 -bench=. -benchmem -timeout 15m

clean:
@- rm -f "$(COP)"
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,31 @@ func usageExample() {
[Here](https://github.com/s0rg/grid/blob/master/_example/main.go) is a full example.

You can run it with `go run _example/main.go` to see results.

# benchmarks

run:

```bash
make bench
```

results:

```
goos: linux
goarch: amd64
pkg: github.com/s0rg/grid
cpu: AMD Ryzen 5 5500U with Radeon Graphics
BenchmarkGet-12 45999506 26.23 ns/op 0 B/op 0 allocs/op
BenchmarkSet-12 40784006 25.91 ns/op 0 B/op 0 allocs/op
BenchmarkNeighbours-12 21348812 49.75 ns/op 0 B/op 0 allocs/op
BenchmarkLineBresenham-12 4515738 259.9 ns/op 0 B/op 0 allocs/op
BenchmarkRayCast-12 2857318 415.0 ns/op 0 B/op 0 allocs/op
BenchmarkCastShadow-12 44434 26627 ns/op 0 B/op 0 allocs/op
BenchmarkLineOfSight-12 14748 81038 ns/op 0 B/op 0 allocs/op
BenchmarkDijkstraMap-12 739 1641456 ns/op 20656 B/op 3 allocs/op
BenchmarkPath-12 122 8679218 ns/op 10457551 B/op 36911 allocs/op
PASS
ok github.com/s0rg/grid 13.269s
```
199 changes: 199 additions & 0 deletions grid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package grid

import (
"image"
"math/rand"
"testing"
"time"

"github.com/s0rg/set"
)
Expand Down Expand Up @@ -633,3 +635,200 @@ func TestLineBresenhamBreak(t *testing.T) {
return false
})
}

// benchmarks

const benchmarkSide = 100

var benchmarkSeed = time.Now().UnixNano()

func BenchmarkGet(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))

b.ResetTimer()

for n := 0; n < b.N; n++ {
p := randPoint(benchmarkSide)
_, _ = m.Get(p)
}
}

func BenchmarkSet(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))

b.ResetTimer()

for n := 0; n < b.N; n++ {
p := randPoint(benchmarkSide)
_ = m.Set(p, struct{}{})
}
}

func BenchmarkNeighbours(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))
d := Points(DirectionsALL...)
f := func(_ image.Point, _ struct{}) bool {
return true
}

b.ResetTimer()

for n := 0; n < b.N; n++ {
p := randPoint(benchmarkSide)
m.Neighbours(p, d, f)
}
}

func BenchmarkLineBresenham(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))
f := func(_ image.Point, _ struct{}) (next bool) {
return true
}

b.ResetTimer()

for n := 0; n < b.N; n++ {
a, b := randPoint(benchmarkSide), randPoint(benchmarkSide)
m.LineBresenham(a, b, f)
}
}

func BenchmarkRayCast(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))
f := func(_ image.Point, _ float64, _ struct{}) (next bool) {
return true
}

const (
angleMin = 0.0
angleMax = 360.0
distMin = float64(benchmarkSide / 2)
distMax = float64(benchmarkSide)
)

b.ResetTimer()

for n := 0; n < b.N; n++ {
m.CastRay(
randPoint(benchmarkSide),
randFloat(angleMin, angleMax),
randFloat(distMin, distMax),
f,
)
}
}

func BenchmarkCastShadow(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))
f := func(_ image.Point, _ float64, _ struct{}) (next bool) {
return true
}

const (
distMin = float64(benchmarkSide / 10)
distMax = float64(benchmarkSide / 2)
)

b.ResetTimer()

for n := 0; n < b.N; n++ {
m.CastShadow(
randPoint(benchmarkSide),
randFloat(distMin, distMax),
f,
)
}
}

func BenchmarkLineOfSight(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))
f := func(_ image.Point, _ float64, _ struct{}) (next bool) {
return true
}

const (
distMin = float64(benchmarkSide / 10)
distMax = float64(benchmarkSide / 2)
)

b.ResetTimer()

for n := 0; n < b.N; n++ {
m.LineOfSight(
randPoint(benchmarkSide),
randFloat(distMin, distMax),
f,
)
}
}

func BenchmarkDijkstraMap(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))
f := func(_ image.Point, _ struct{}) (next bool) {
return true
}

const (
pointsMax = 5
)

points := make([]image.Point, pointsMax)

for i := 0; i < pointsMax; i++ {
points[i] = randPoint(benchmarkSide)
}

b.ResetTimer()

for n := 0; n < b.N; n++ {
m.DijkstraMap(points, f)
}
}

func BenchmarkPath(b *testing.B) {
rand.Seed(benchmarkSeed)

m := New[struct{}](image.Rect(0, 0, benchmarkSide, benchmarkSide))
d := Points(DirectionsCardinal...)
f := func(_ image.Point, dist float64, _ struct{}) (cost float64, walkable bool) {
return dist, true
}

b.ResetTimer()

for n := 0; n < b.N; n++ {
a, b := randPoint(benchmarkSide), randPoint(benchmarkSide)
m.Path(a, b, d, DistanceManhattan, f)
}
}

func randPoint(a int) image.Point {
return image.Pt(
randInt(1, a),
randInt(1, a),
)
}

func randInt(a, b int) (rv int) {
return a + rand.Intn(b-a)
}

func randFloat(min, max float64) (rv float64) {
return min + (rand.Float64() * (max - min))
}
18 changes: 10 additions & 8 deletions path.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@ type path struct {
Cost float64
}

func (p path) Len() (rv int) {
func (p *path) Len() (rv int) {
return len(p.Points)
}

func (p path) Last() (v image.Point) {
func (p *path) Last() (v image.Point) {
return p.Points[p.Len()-1]
}

func (p path) Fork(pt image.Point, dist float64) (rv path) {
func (p *path) Fork(pt image.Point, dist float64) (rv path) {
l := p.Len()
points := make([]image.Point, l, l+1)
copy(points, p.Points)
add := make([]image.Point, l+1)
copy(add, p.Points)

rv.Points = append(points, pt)
rv.Cost = p.Cost + dist
add[l] = pt

return rv
return path{
Points: add,
Cost: p.Cost + dist,
}
}
17 changes: 5 additions & 12 deletions pqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,13 @@ package grid

type pqueue []path

func (q pqueue) Len() int { return len(q) }
func (q pqueue) Less(i, j int) bool { return q[i].Cost < q[j].Cost }
func (q pqueue) Swap(i, j int) { q[i], q[j] = q[j], q[i] }

func (q *pqueue) Push(x any) {
*q = append(*q, x.(path))
}
func (q *pqueue) Len() int { return len(*q) }
func (q *pqueue) Less(i, j int) bool { return (*q)[i].Cost < (*q)[j].Cost }
func (q *pqueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
func (q *pqueue) Push(x any) { *q = append(*q, x.(path)) }

func (q *pqueue) Pop() (x any) {
t := *q
n := t.Len()

x = t[n-1]
*q = t[0 : n-1]
*q, x = (*q)[:q.Len()-1], (*q)[q.Len()-1]

return x
}

0 comments on commit b46676b

Please sign in to comment.