webp
webp copied to clipboard
memory leak
I create a simple http server do convert a jpg to webp
here is the sample code:
func ImgTowebp(imgData []byte) ([]byte, error) {
//jpeg.Decode()
img, err := jpeg.Decode(bytes.NewBuffer(imgData))
if err != nil {
//log.Println("decode error from jpg",err)
img, err = png.Decode(bytes.NewBuffer(imgData))
if err != nil {
log.Println("decode error from png or jpg", err)
return nil, err
}
}
//log.Println(fname)
webImgBytes, err := webp.EncodeRGBA(img, 80)
if err == nil {
webpLength := len(webImgBytes)
imgLength := len(imgData)
if webpLength > imgLength {
log.Println("webp bigger than img")
}
log.Println("img2webp <webp size>:<img size>", webpLength, ":", imgLength)
return webImgBytes, nil
} else {
log.Println("webp encode jpg file", err)
return nil, err
}
}
main.go
webImgBytes, err := ImgTowebp(bodybuffer)
if err == nil {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "image/webp")
w.Write(webImgBytes)
return
}
运行一段时间后, 内存分析图:
查看 相关源代码:
func EncodeRGBA(m image.Image, quality float32) (data []byte, err error) {
p := toRGBAImage(m)
data, err = webpEncodeRGBA(p.Pix, p.Rect.Dx(), p.Rect.Dy(), p.Stride, quality)
return
}
func toRGBAImage(m image.Image) *image.RGBA {
if m, ok := m.(*image.RGBA); ok {
return m
}
b := m.Bounds()
rgba := image.NewRGBA(b)
dstColorRGBA64 := &color.RGBA64{}
dstColor := color.Color(dstColorRGBA64)
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
pr, pg, pb, pa := m.At(x, y).RGBA()
dstColorRGBA64.R = uint16(pr)
dstColorRGBA64.G = uint16(pg)
dstColorRGBA64.B = uint16(pb)
dstColorRGBA64.A = uint16(pa)
rgba.Set(x, y, dstColor)
}
}
return rgba
}
func webpEncodeRGB(pix []byte, width, height, stride int, quality float32) (output []byte, err error) {
if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 || quality < 0.0 {
err = errors.New("webpEncodeRGB: bad arguments")
return
}
if stride < width*3 && len(pix) < height*stride {
err = errors.New("webpEncodeRGB: bad arguments")
return
}
//主要怀疑 (*C.uint8_t)(unsafe.Pointer(&pix[0])) 这个是golang分配的图片pix数组, 传递到CGO后,没有进行释放,就一直持有。
///
var cptr_size C.size_t
var cptr = C.webpEncodeRGB(
(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
C.int(stride), C.float(quality),
&cptr_size,
)
if cptr == nil || cptr_size == 0 {
err = errors.New("webpEncodeRGB: failed")
return
}
defer C.free(unsafe.Pointer(cptr))
output = make([]byte, int(cptr_size))
copy(output, ((*[1 << 30]byte)(unsafe.Pointer(cptr)))[0:len(output):len(output)])
return
}
图是heap inuse_space, heap 对象数 一直加,没见降
golang 1.13.5 centos 6 64位
顶,我也发现了这个问题
解决了吗
Test Environments
go version
go version go1.13.3 darwin/amd64
go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="==security_stuff=="
GOENV="==security_stuff=="
GOEXE=""
GOFLAGS=" -mod="
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="==security_stuff=="
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="==security_stuff=="
Summary
I did profiling to next code and the result, I got chart of the memory allocated. So i think this library haven't memory leak it's my concluding.
package main
import (
"bytes"
"fmt"
"github.com/chai2010/webp"
_ "github.com/mkevac/debugcharts"
"image/jpeg"
"io/ioutil"
"log"
"net/http"
_ "net/http/pprof"
"time"
)
func main() {
go func() {
http.ListenAndServe(":3030", nil)
}()
i := 0
for {
time.Sleep(time.Second / 10)
imgData, err := ioutil.ReadFile("test2.jpeg")
img, err := jpeg.Decode(bytes.NewBuffer(imgData))
if err != nil {
log.Println(err)
}
output, err := webp.EncodeRGBA(img, 80)
if err != nil {
log.Println(err)
}
if output != nil {
}
fmt.Println("Save output.webp ok", i)
i++
}
}