首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编码base64时的内存消耗

编码base64时的内存消耗
EN

Stack Overflow用户
提问于 2022-01-26 13:04:23
回答 2查看 368关注 0票数 -1

我在使用golangs编码/ have 64的软件中的内存消耗有问题。

我的软件将一个视频文件分割成单独的图像,(gocv )将它们转换为base64字符串,并将其保存为json格式的文件。

在测试过程中,我发现内存的使用一直在堆积,直到oom收割机扼杀了这个过程。

pprof的研究表明,编码/base64 64内存似乎堆积起来了。

我在每个图像帧后做了pprof快照,并分配给我编码/base64 64正在从976.89kB(平面)上升到4633.54kB(平面),就在oom-收割机正在扼杀这个过程之前。

代码语言:javascript
复制
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

列表显示了它所遵循的代码:

代码语言:javascript
复制
(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

所以在我的戈朗代码中,对应的代码行是:

代码语言:javascript
复制
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-泄漏是在lib base64上吗?(最新消息:答案是肯定不是这样的)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-27 11:29:00

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

Base64根本不是问题,它只是显示在pprof上的内存的最大消费者,这给我带来了一个错误的结论,即base64是问题所在。

我猜pprof会告诉我我的围棋程序的所有消费,包括gocv。gocv是opencv的c包装器,但是它的大量消耗对pprof来说是不可见的,因为它是c代码!(我在问这个问题时不知道这一点)。由于pprof而可见的内存消耗没有显示c-包装器库为go (如gocv )所使用的内存。在戈朗看来,大部分的内存消耗是看不见的。因此,JimB的帮助提示是:

看到如何在opencv上使用Go包装器,您所关心的内存可能甚至没有被Go分配。在这种情况下,您确实需要确保所有东西都可能根据文档关闭或发布,因为大部分工作是用C++完成的,而不是Go。然而,即使您正在正确地清理,您仍然需要意识到您的内存限制,并确保您没有试图在任何给定的时间点保存太多的数据。

当我清理gocv的物品时,我的消耗大大减少了。我过去常常关闭物体:

代码语言:javascript
复制
defer obj.close()
票数 -1
EN

Stack Overflow用户

发布于 2022-01-26 13:47:56

回答你的问题:

--在这种情况下,如何释放"encodedString“的内存?

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

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

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

为指导您找到解决方案:

您的应用程序使用了荒谬的内存量,但这是因为( a)处理视频和图像需要内存,b)您似乎没有做任何事情来保持内存低:例如,您将整个图像编码为一个bytes.Buffer,然后将整个bytes.Buffer编码为一个字符串,然后处理该字符串等等。您可能应该将图像编码为流,将该流编码为base64,并将此输出进一步流到其存放的位置。这是完全没有痛苦的去,因为所有这些编码器工作在io.Writers上,可以很容易地链接。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70863870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档