mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 03:02:49 +01:00
internal/affine: Improve ColorM Scale's performance
The benchmark result comparing the previous commit and this commit is this: ``` name old time/op new time/op delta ColorMScale-8 9.75µs ± 6% 1.30µs ±22% -86.67% (p=0.000 n=10+9) name old alloc/op new alloc/op delta ColorMScale-8 1.34kB ±100% 1.19kB ±19% ~ (p=0.421 n=10+8) name old allocs/op new allocs/op delta ColorMScale-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=10+10) ``` Updates #1658
This commit is contained in:
parent
79e067b0f8
commit
59aa41a3c2
@ -18,7 +18,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ColorMDim is a dimension of a ColorM.
|
// ColorMDim is a dimension of a ColorM.
|
||||||
@ -104,7 +103,7 @@ func (c ColorMIdentity) IsIdentity() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) IsIdentity() bool {
|
func (c colorMImplScale) IsIdentity() bool {
|
||||||
return c.scale == [4]float32{1, 1, 1, 1}
|
return c.scale == [4]float32{1, 1, 1, 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +115,7 @@ func (c ColorMIdentity) ScaleOnly() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) ScaleOnly() bool {
|
func (c colorMImplScale) ScaleOnly() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +168,7 @@ func (c ColorMIdentity) UnsafeScaleElements() *[4]float32 {
|
|||||||
return &[...]float32{1, 1, 1, 1}
|
return &[...]float32{1, 1, 1, 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) UnsafeScaleElements() *[4]float32 {
|
func (c colorMImplScale) UnsafeScaleElements() *[4]float32 {
|
||||||
return &c.scale
|
return &c.scale
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +199,7 @@ func (c ColorMIdentity) Apply(clr color.Color) color.Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Apply(clr color.Color) color.Color {
|
func (c colorMImplScale) Apply(clr color.Color) color.Color {
|
||||||
rf, gf, bf, af := colorToFloat32s(clr)
|
rf, gf, bf, af := colorToFloat32s(clr)
|
||||||
rf *= c.scale[0]
|
rf *= c.scale[0]
|
||||||
gf *= c.scale[1]
|
gf *= c.scale[1]
|
||||||
@ -242,7 +241,7 @@ func (c ColorMIdentity) UnsafeElements() (*[16]float32, *[4]float32) {
|
|||||||
return &colorMIdentityBody, &colorMIdentityTranslate
|
return &colorMIdentityBody, &colorMIdentityTranslate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) UnsafeElements() (*[16]float32, *[4]float32) {
|
func (c colorMImplScale) UnsafeElements() (*[16]float32, *[4]float32) {
|
||||||
return &[...]float32{
|
return &[...]float32{
|
||||||
c.scale[0], 0, 0, 0,
|
c.scale[0], 0, 0, 0,
|
||||||
0, c.scale[1], 0, 0,
|
0, c.scale[1], 0, 0,
|
||||||
@ -290,7 +289,7 @@ func (c ColorMIdentity) IsInvertible() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) IsInvertible() bool {
|
func (c colorMImplScale) IsInvertible() bool {
|
||||||
return c.scale[0] != 0 && c.scale[1] != 0 && c.scale[2] != 0 && c.scale[3] != 0
|
return c.scale[0] != 0 && c.scale[1] != 0 && c.scale[2] != 0 && c.scale[3] != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,8 +301,8 @@ func (c ColorMIdentity) Invert() ColorM {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Invert() ColorM {
|
func (c colorMImplScale) Invert() ColorM {
|
||||||
return &colorMImplScale{
|
return colorMImplScale{
|
||||||
scale: [4]float32{
|
scale: [4]float32{
|
||||||
1 / c.scale[0],
|
1 / c.scale[0],
|
||||||
1 / c.scale[1],
|
1 / c.scale[1],
|
||||||
@ -449,7 +448,7 @@ func (c ColorMIdentity) Equals(other ColorM) bool {
|
|||||||
return other.IsIdentity()
|
return other.IsIdentity()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Equals(other ColorM) bool {
|
func (c colorMImplScale) Equals(other ColorM) bool {
|
||||||
if !other.ScaleOnly() {
|
if !other.ScaleOnly() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -472,7 +471,7 @@ func (c ColorMIdentity) Concat(other ColorM) ColorM {
|
|||||||
return other
|
return other
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Concat(other ColorM) ColorM {
|
func (c colorMImplScale) Concat(other ColorM) ColorM {
|
||||||
if other.IsIdentity() {
|
if other.IsIdentity() {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@ -518,11 +517,13 @@ func (c *colorMImplBodyTranslate) Concat(other ColorM) ColorM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c ColorMIdentity) Scale(r, g, b, a float32) ColorM {
|
func (c ColorMIdentity) Scale(r, g, b, a float32) ColorM {
|
||||||
return getCachedScalingColorM(r, g, b, a)
|
return colorMImplScale{
|
||||||
|
scale: [...]float32{r, g, b, a},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Scale(r, g, b, a float32) ColorM {
|
func (c colorMImplScale) Scale(r, g, b, a float32) ColorM {
|
||||||
return &colorMImplScale{
|
return colorMImplScale{
|
||||||
scale: [...]float32{
|
scale: [...]float32{
|
||||||
c.scale[0] * r,
|
c.scale[0] * r,
|
||||||
c.scale[1] * g,
|
c.scale[1] * g,
|
||||||
@ -535,7 +536,9 @@ func (c *colorMImplScale) Scale(r, g, b, a float32) ColorM {
|
|||||||
func (c *colorMImplBodyTranslate) Scale(r, g, b, a float32) ColorM {
|
func (c *colorMImplBodyTranslate) Scale(r, g, b, a float32) ColorM {
|
||||||
if c.ScaleOnly() {
|
if c.ScaleOnly() {
|
||||||
s := c.UnsafeScaleElements()
|
s := c.UnsafeScaleElements()
|
||||||
return getCachedScalingColorM(r*s[0], g*s[1], b*s[2], a*s[3])
|
return colorMImplScale{
|
||||||
|
scale: [...]float32{r * s[0], g * s[1], b * s[2], a * s[3]},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eb := c.body
|
eb := c.body
|
||||||
@ -566,7 +569,7 @@ func (c ColorMIdentity) Translate(r, g, b, a float32) ColorM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Translate(r, g, b, a float32) ColorM {
|
func (c colorMImplScale) Translate(r, g, b, a float32) ColorM {
|
||||||
return &colorMImplBodyTranslate{
|
return &colorMImplBodyTranslate{
|
||||||
body: [...]float32{
|
body: [...]float32{
|
||||||
c.scale[0], 0, 0, 0,
|
c.scale[0], 0, 0, 0,
|
||||||
@ -647,48 +650,3 @@ type cachedScalingColorMValue struct {
|
|||||||
c *colorMImplScale
|
c *colorMImplScale
|
||||||
atime uint64
|
atime uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
cachedScalingColorM = map[cachedScalingColorMKey]*cachedScalingColorMValue{}
|
|
||||||
cachedScalingColorMM sync.Mutex
|
|
||||||
cacheMonotonicClock uint64
|
|
||||||
)
|
|
||||||
|
|
||||||
func getCachedScalingColorM(r, g, b, a float32) ColorM {
|
|
||||||
key := cachedScalingColorMKey{r, g, b, a}
|
|
||||||
|
|
||||||
cachedScalingColorMM.Lock()
|
|
||||||
defer cachedScalingColorMM.Unlock()
|
|
||||||
|
|
||||||
cacheMonotonicClock++
|
|
||||||
now := cacheMonotonicClock
|
|
||||||
|
|
||||||
if v, ok := cachedScalingColorM[key]; ok {
|
|
||||||
v.atime = now
|
|
||||||
return v.c
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxCacheSize = 512 // An arbitrary number
|
|
||||||
|
|
||||||
for len(cachedScalingColorM) >= maxCacheSize {
|
|
||||||
var oldest uint64 = math.MaxUint64
|
|
||||||
var oldestKey cachedScalingColorMKey
|
|
||||||
for k, v := range cachedScalingColorM {
|
|
||||||
if v.atime < oldest {
|
|
||||||
oldestKey = k
|
|
||||||
oldest = v.atime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete(cachedScalingColorM, oldestKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := &cachedScalingColorMValue{
|
|
||||||
c: &colorMImplScale{
|
|
||||||
scale: [...]float32{r, g, b, a},
|
|
||||||
},
|
|
||||||
atime: now,
|
|
||||||
}
|
|
||||||
cachedScalingColorM[key] = v
|
|
||||||
|
|
||||||
return v.c
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user