From 827e20d84d0ce049c83445a1c8805d001c24b65a Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Thu, 5 Jan 2023 16:05:38 +0200 Subject: [PATCH] gpu: optimize pack.tryAdd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta Packer-32 559µs ± 2% 295µs ± 1% -47.18% (p=0.008 n=5+5) Signed-off-by: Egon Elbre --- gpu/pack.go | 24 ++++++++++++++---------- gpu/pack_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 gpu/pack_test.go diff --git a/gpu/pack.go b/gpu/pack.go index 3f8c9250..cb0ca023 100644 --- a/gpu/pack.go +++ b/gpu/pack.go @@ -46,20 +46,24 @@ func (p *packer) newPage() { } func (p *packer) tryAdd(s image.Point) (placement, bool) { + if len(p.spaces) == 0 || len(p.sizes) == 0 { + return placement{}, false + } + var ( - bestIdx = -1 - bestSpace image.Rectangle - bestSize = p.maxDims + bestIdx *image.Rectangle + bestSize = p.maxDims + lastSize = p.sizes[len(p.sizes)-1] ) // Go backwards to prioritize smaller spaces. - for i, space := range p.spaces { + for i := range p.spaces { + space := &p.spaces[i] rightSpace := space.Dx() - s.X bottomSpace := space.Dy() - s.Y if rightSpace < 0 || bottomSpace < 0 { continue } - idx := len(p.sizes) - 1 - size := p.sizes[idx] + size := lastSize if x := space.Min.X + s.X; x > size.X { if x > p.maxDims.X { continue @@ -73,16 +77,16 @@ func (p *packer) tryAdd(s image.Point) (placement, bool) { size.Y = y } if size.X*size.Y < bestSize.X*bestSize.Y { - bestIdx = i - bestSpace = space + bestIdx = space bestSize = size } } - if bestIdx == -1 { + if bestIdx == nil { return placement{}, false } // Remove space. - p.spaces[bestIdx] = p.spaces[len(p.spaces)-1] + bestSpace := *bestIdx + *bestIdx = p.spaces[len(p.spaces)-1] p.spaces = p.spaces[:len(p.spaces)-1] // Put s in the top left corner and add the (at most) // two smaller spaces. diff --git a/gpu/pack_test.go b/gpu/pack_test.go new file mode 100644 index 00000000..98db6eb5 --- /dev/null +++ b/gpu/pack_test.go @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package gpu + +import ( + "image" + "testing" +) + +func BenchmarkPacker(b *testing.B) { + var p packer + p.maxDims = image.Point{X: 4096, Y: 4096} + for i := 0; i < b.N; i++ { + p.clear() + p.newPage() + for k := 0; k < 500; k++ { + _, ok := p.tryAdd(xy(k)) + if !ok { + b.Fatal("add failed", i, k, xy(k)) + } + } + } +} + +func xy(v int) image.Point { + return image.Point{ + X: ((v / 16) % 16) + 8, + Y: (v % 16) + 8, + } +}