internal/atlas: Reuse byte array for ReplacePixels

This reduces memory allocation at ReplacePixels.

Updates #1681
This commit is contained in:
Hajime Hoshi 2021-06-26 02:33:14 +09:00
parent 371bbfc0f2
commit 38ce46328a
2 changed files with 60 additions and 3 deletions

View File

@ -38,6 +38,53 @@ var (
maxSize = 0
)
type temporaryPixels struct {
pixels []byte
pos int
totalUse int
unusedTime int
}
var theTemporaryPixels temporaryPixels
func (t *temporaryPixels) alloc(size int) []byte {
if len(t.pixels) < t.pos+size {
newL := len(t.pixels)
if newL == 0 {
newL = 16
}
for newL < t.pos+size {
newL *= 2
}
t.pixels = make([]byte, newL)
t.pos = 0
}
pix := t.pixels[t.pos : t.pos+size]
t.pos += size
t.totalUse += size
return pix
}
func (t *temporaryPixels) resetAtFrameEnd() {
const maxUnusedTime = 60
if t.totalUse == 0 {
if t.unusedTime < maxUnusedTime {
t.unusedTime++
}
} else {
t.unusedTime = 0
}
// Let the pixels GCed if this is not used for a while.
if t.unusedTime == maxUnusedTime && len(t.pixels) > 0 {
t.pixels = nil
}
t.pos = 0
t.totalUse = 0
}
func max(a, b int) int {
if a > b {
return a
@ -487,7 +534,7 @@ func (i *Image) replacePixels(pix []byte) {
}
// Add a padding around the image.
pixb := make([]byte, 4*w*h)
pixb := theTemporaryPixels.alloc(4 * w * h)
for j := 0; j < oh; j++ {
copy(pixb[4*((j+paddingSize)*w+paddingSize):], pix[4*j*ow:4*(j+1)*ow])
}
@ -700,6 +747,8 @@ func NewScreenFramebufferImage(width, height int) *Image {
func EndFrame() error {
backendsM.Lock()
theTemporaryPixels.resetAtFrameEnd()
return restorable.ResolveStaleImages()
}

View File

@ -304,7 +304,11 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
if x == 0 && y == 0 && width == w && height == h {
if pixels != nil {
i.basePixels.AddOrReplace(pixels, 0, 0, w, h)
// pixels can point to a shared region.
// This function is responsible to copy this.
copiedPixels := make([]byte, len(pixels))
copy(copiedPixels, pixels)
i.basePixels.AddOrReplace(copiedPixels, 0, 0, w, h)
} else {
i.basePixels.Remove(0, 0, w, h)
}
@ -324,7 +328,11 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
}
if pixels != nil {
i.basePixels.AddOrReplace(pixels, x, y, width, height)
// pixels can point to a shared region.
// This function is responsible to copy this.
copiedPixels := make([]byte, len(pixels))
copy(copiedPixels, pixels)
i.basePixels.AddOrReplace(copiedPixels, x, y, width, height)
} else {
i.basePixels.Remove(x, y, width, height)
}