基于编码64的内存消耗



我的软件使用golangs lib编码/base64 时内存消耗有问题

我的软件正在将视频文件拆分为单独的图像,(gov-mat(将它们转换为base64字符串,并将其保存为json格式的文件。

在测试过程中,我发现内存使用量不断增加,直到收割者正在扼杀这个过程。

对pprof的调查表明,编码/base64内存似乎堆积起来了。

我在每个图像帧后进行了大约f次快照,并分配了编码/base64从976.89kB(平坦(提高到4633.54kB(平坦的(,就在oom收割者杀死这个过程之前不久。

Beginning:
flat  flat%   sum%        cum   cum%
976.89kB 32.29% 32.29%   976.89kB 32.29%  encoding/base64.(*Encoding).EncodeToString
512.50kB 16.94% 49.23%   512.50kB 16.94%  runtime.allocm
512.20kB 16.93% 66.15%   512.20kB 16.93%  runtime.malg
512.05kB 16.92% 83.08%  1488.94kB 49.21%  runtime.main
512kB 16.92%   100%      512kB 16.92%  time.resetTimer (inline)
0     0%   100%   976.89kB 32.29%  main.Process
End:
Showing nodes accounting for 6170.44kB, 100% of 6170.44kB total
flat  flat%   sum%        cum   cum%
4633.54kB 75.09% 75.09%  4633.54kB 75.09%  encoding/base64.(*Encoding).EncodeToString
1024.41kB 16.60% 91.69%  1024.41kB 16.60%  runtime.malg
512.50kB  8.31%   100%   512.50kB  8.31%  runtime.allocm
0     0%   100%  4633.54kB 75.09%  main.Process

列表显示了相应的代码:

(pprof) list encoding/base64
Total: 2.95MB
ROUTINE ======================== encoding/base64.(*Encoding).EncodeToString in /usr/local/go/src/encoding/base64/base64.go
976.89kB   976.89kB (flat, cum) 32.29% of Total
.          .    175:
.          .    176:// EncodeToString returns the base64 encoding of src.
.          .    177:func (enc *Encoding) EncodeToString(src []byte) string {
.          .    178:   buf := make([]byte, enc.EncodedLen(len(src)))
.          .    179:   enc.Encode(buf, src)
976.89kB   976.89kB    180:   return string(buf)
.          .    181:}
.          .    182:
.          .    183:type encoder struct {
.          .    184:   err  error
.          .    185:   enc  *Encoding

所以在我的golang代码中,相应的代码行是:

func Process(img gocv.Mat) ( myImage Images  ){
detectImg, detectClass, detectBoxes := Detect(&net, 
img.Clone(), 
0.45, 0.5, 
OutputNames, classes)
defer detectImg.Close()
// convert gocv.Mat to []bytes
myImg , _ := detectImg.ToImage()
myJPG := new(bytes.Buffer)
jpeg.Encode(myJPG, myImg, &jpeg.Options{95})
myBytes := myJPG.Bytes()

// memory consuming
encodedString := base64.StdEncoding.EncodeToString(myBytes)
// [...]
return myImage
}

我怎样才能释放";encodedString";在这种情况下,它不会堆积起来?(更新:答案说这不是必要的,也不可能(

或者这可能不是我的错误编码,而mem泄漏在libbase64??(更新:答案表明肯定不是这样(

回答您的问题:

我如何才能释放"encodedString";在这种情况下,它不会堆积起来?

你不能也不需要。未使用的存储器是";释放";。

或者这可能不是我的错误编码,而mem泄漏在lib-base64?

否,包编码/base64没有内存泄漏。(在垃圾收集语言的标准库中,在一个微不足道的函数中检测到内存泄漏的可能性为0。(

引导您找到解决方案:

您的应用程序使用了荒谬的内存量,但这是因为a(处理视频和图像内存不足,b(您似乎没有采取任何措施来保持低内存:例如,您将整个图像编码为字节。缓冲区,然后对整个字节进行编码。缓冲到一个字符串,然后处理该字符串,依此类推。您可能应该将图像编码到中,将该编码到base64,并将该输出进一步编码到其存放的位置。这在Go中是完全无痛的,因为所有这些编码器都在io上工作。编写器可以很容易地链接起来。

我上面的问题完全错了。

Base64根本不是问题所在,它只是内存的最大消耗者显示在pprof上,导致我得出错误的结论,即base64就是问题所在。

我猜pprf会告诉我所有内存消耗我的围棋项目,包括围棋。govv是opencv的c包装器,但它的mem消耗对pprf来说是不可见的,因为它是c代码!(我问这个问题时并不知道(。由于approf而可见的内存消耗未显示类似gocv的c-wrapper库使用的内存。戈兰根本看不到内存消耗的大部分。所以JimB的帮助提示是:

看看你是如何在opencv周围使用Go包装器的可能连围棋都没有分配。那样的话你确实需要确保所有的东西都可能被关闭或释放根据他们的文件,因为大部分工作已经完成在C++中,而不是Go。即使你打扫得很好仍然需要意识到你的记忆力限制,并确保你不试图在任何给定点保存太多数据。

当我清理gov对象时,内存消耗显著下降。我曾经关闭过物体:

defer obj.close()

最新更新