forked from joejulian/gio
gpu: optimize pack.tryAdd
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 <egonelbre@gmail.com>
This commit is contained in:
+14
-10
@@ -46,20 +46,24 @@ func (p *packer) newPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *packer) tryAdd(s image.Point) (placement, bool) {
|
func (p *packer) tryAdd(s image.Point) (placement, bool) {
|
||||||
|
if len(p.spaces) == 0 || len(p.sizes) == 0 {
|
||||||
|
return placement{}, false
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bestIdx = -1
|
bestIdx *image.Rectangle
|
||||||
bestSpace image.Rectangle
|
bestSize = p.maxDims
|
||||||
bestSize = p.maxDims
|
lastSize = p.sizes[len(p.sizes)-1]
|
||||||
)
|
)
|
||||||
// Go backwards to prioritize smaller spaces.
|
// 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
|
rightSpace := space.Dx() - s.X
|
||||||
bottomSpace := space.Dy() - s.Y
|
bottomSpace := space.Dy() - s.Y
|
||||||
if rightSpace < 0 || bottomSpace < 0 {
|
if rightSpace < 0 || bottomSpace < 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
idx := len(p.sizes) - 1
|
size := lastSize
|
||||||
size := p.sizes[idx]
|
|
||||||
if x := space.Min.X + s.X; x > size.X {
|
if x := space.Min.X + s.X; x > size.X {
|
||||||
if x > p.maxDims.X {
|
if x > p.maxDims.X {
|
||||||
continue
|
continue
|
||||||
@@ -73,16 +77,16 @@ func (p *packer) tryAdd(s image.Point) (placement, bool) {
|
|||||||
size.Y = y
|
size.Y = y
|
||||||
}
|
}
|
||||||
if size.X*size.Y < bestSize.X*bestSize.Y {
|
if size.X*size.Y < bestSize.X*bestSize.Y {
|
||||||
bestIdx = i
|
bestIdx = space
|
||||||
bestSpace = space
|
|
||||||
bestSize = size
|
bestSize = size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bestIdx == -1 {
|
if bestIdx == nil {
|
||||||
return placement{}, false
|
return placement{}, false
|
||||||
}
|
}
|
||||||
// Remove space.
|
// 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]
|
p.spaces = p.spaces[:len(p.spaces)-1]
|
||||||
// Put s in the top left corner and add the (at most)
|
// Put s in the top left corner and add the (at most)
|
||||||
// two smaller spaces.
|
// two smaller spaces.
|
||||||
|
|||||||
@@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user