为了账号安全,请及时绑定邮箱和手机立即绑定

编码 base64 时的内存消耗

编码 base64 时的内存消耗

Go
慕森王 2022-10-31 15:47:17
我在使用 golangs lib encoding/base64 的软件中遇到内存消耗问题我的软件将视频文件拆分为单独的图像,(gocv mat)将它们转换为base64字符串并将其保存为json格式的文件。在测试过程中,我发现内存使用量一直在增加,直到 oom-reaper 杀死进程。对 pprof 的调查显示编码/base64 内存似乎堆积了起来。我在每个图像帧之后进行了 pprof 快照,并且分配的编码/base64 内存在 oom-reaper 终止进程之前不久从 976.89kB(flat) 增加到 4633.54kB(flat)。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.ProcessEnd: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/base64Total: 2.95MBROUTINE ======================== 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在这种情况下,如何释放“encodedString”的内存而不堆积?(更新:答案说这没有必要也不可能)或者这可能不是我的错误编码,并且内存泄漏位于 lib base64 中?(更新:答案说这肯定不是这种情况)
查看完整描述

2 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

要回答您的问题:

在这种情况下,如何释放“encodedString”的内存而不堆积?

你不能也不需要。未使用的内存被“释放”。

或者这可能不是我的错误编码,而 mem-leak 位于 lib base64 ?

不,包 encoding/base64 没有内存泄漏。(您在垃圾收集语言的标准库中的一个普通函数中检测到内存泄漏的可能性为 0。)

指导您找到解决方案:

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


查看完整回答
反对 回复 2022-10-31
?
慕姐8265434

TA贡献1813条经验 获得超2个赞

我上面的问题是完全错误的方式。

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

我猜 pprof 会告诉我我的 go 程序的所有内存消耗,包括 gocv。gocv 是 opencv 的 ac 包装器,但是 pprof 看不到它的内存消耗,因为它是 c 代码!(我在问这个问题时不知道)。由于 pprof 可见的内存消耗没有显示 c-wrapper 库使用的内存,例如 gocv。golang 根本看不到大部分内存消耗。所以 JimB 的帮助提示是:

看到您如何在 opencv 周围使用 Go 包装器,您关心的内存可能甚至没有被 Go 分配。在这种情况下,您确实需要确保所有内容都可能根据他们的文档关闭或发布,因为大部分工作是在 C++ 中完成的,而不是 Go。但是,即使您正在正确清理,您仍然需要了解您的内存限制,并确保您在任何给定点都不会尝试保存太多数据。

当我清理 gocv 对象时,内存消耗显着下降。我曾经关闭对象:

defer obj.close()


查看完整回答
反对 回复 2022-10-31
  • 2 回答
  • 0 关注
  • 182 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号