Fix another ~300 allocations per frame in my test project (#1089)

This simple change brings my simple test project from 752 allocations per frame to 474 allocations per frame. It seems a shame that go's escape analysis is not smart enough to leave this variable on the stack.

GeoM is a 24-byte struct and there is a slight perf difference that we are storing it in stack, but also copying it around with this change (instead of an 8-byte pointer). This could make things faster (due to stack / CPU cache) or slower (due to copying more memory) - when I try a stress test (drawing 100K images per frame), I can't see any actual performance difference (but I do see 100K fewer allocations, and GC is no longer running almost all the time).
This commit is contained in:
corfe83 2020-02-21 20:40:17 -08:00 committed by GitHub
parent 7ea56b2e79
commit b3c567de89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 5 additions and 5 deletions

View File

@ -214,7 +214,7 @@ func (i *Image) DrawImage(src *Image, bounds image.Rectangle, a, b, c, d, tx, ty
panic("buffered: Image.DrawImage: src must be different from the receiver") panic("buffered: Image.DrawImage: src must be different from the receiver")
} }
g := &mipmap.GeoM{ g := mipmap.GeoM{
A: a, A: a,
B: b, B: b,
C: c, C: c,
@ -237,7 +237,7 @@ func (i *Image) DrawImage(src *Image, bounds image.Rectangle, a, b, c, d, tx, ty
i.drawImage(src, bounds, g, colorm, mode, filter) i.drawImage(src, bounds, g, colorm, mode, filter)
} }
func (i *Image) drawImage(src *Image, bounds image.Rectangle, g *mipmap.GeoM, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter) { func (i *Image) drawImage(src *Image, bounds image.Rectangle, g mipmap.GeoM, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter) {
src.resolvePendingPixels(true) src.resolvePendingPixels(true)
i.resolvePendingPixels(false) i.resolvePendingPixels(false)
i.img.DrawImage(src.img, bounds, g, colorm, mode, filter) i.img.DrawImage(src.img, bounds, g, colorm, mode, filter)

View File

@ -96,7 +96,7 @@ func (m *Mipmap) At(x, y int) (r, g, b, a byte, err error) {
return m.orig.At(x, y) return m.orig.At(x, y)
} }
func (m *Mipmap) DrawImage(src *Mipmap, bounds image.Rectangle, geom *GeoM, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter) { func (m *Mipmap) DrawImage(src *Mipmap, bounds image.Rectangle, geom GeoM, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter) {
if det := geom.det(); det == 0 { if det := geom.det(); det == 0 {
return return
} else if math.IsNaN(float64(det)) { } else if math.IsNaN(float64(det)) {
@ -275,7 +275,7 @@ func (m *Mipmap) disposeMipmaps() {
// mipmapLevel returns an appropriate mipmap level for the given determinant of a geometry matrix. // mipmapLevel returns an appropriate mipmap level for the given determinant of a geometry matrix.
// //
// mipmapLevel panics if det is NaN or 0. // mipmapLevel panics if det is NaN or 0.
func (m *Mipmap) mipmapLevel(geom *GeoM, width, height int, filter driver.Filter) int { func (m *Mipmap) mipmapLevel(geom GeoM, width, height int, filter driver.Filter) int {
det := geom.det() det := geom.det()
if math.IsNaN(float64(det)) { if math.IsNaN(float64(det)) {
panic("ebiten: det must be finite at mipmapLevel") panic("ebiten: det must be finite at mipmapLevel")
@ -294,7 +294,7 @@ func (m *Mipmap) mipmapLevel(geom *GeoM, width, height int, filter driver.Filter
if !graphicsDriver.HasHighPrecisionFloat() { if !graphicsDriver.HasHighPrecisionFloat() {
tooBigScale = 4 tooBigScale = 4
} }
if sx, sy := geomScaleSize(geom); sx >= tooBigScale || sy >= tooBigScale { if sx, sy := geomScaleSize(&geom); sx >= tooBigScale || sy >= tooBigScale {
// If the filter is not nearest, the target needs to be rendered with graduation. Don't use mipmaps. // If the filter is not nearest, the target needs to be rendered with graduation. Don't use mipmaps.
if filter != driver.FilterNearest { if filter != driver.FilterNearest {
return 0 return 0