golang读取XML内存泄漏?

Posted

技术标签:

【中文标题】golang读取XML内存泄漏?【英文标题】:golang reading XML memory leak? 【发布时间】:2014-01-30 22:54:24 【问题描述】:

我们最近使用 golang 和 encoding/xml 解码了很多 XML。我们注意到,在相当多的文件之后,我们的盒子内存不足,开始交换,并且通常会不幸死去。所以我们做了一个测试程序。这里是:

package main

import (
    "encoding/xml"
    "io/ioutil"
    "log"
    "time"
)

// this XML is for reading AWS SQS messages
type message struct 
    Body          []string `xml:"ReceiveMessageResult>Message>Body"`
    ReceiptHandle []string `xml:"ReceiveMessageResult>Message>ReceiptHandle"`


func main() 
    var m message

    readTicker := time.NewTicker(5 * time.Millisecond)

    body, err := ioutil.ReadFile("test.xml")

    for 
        select 
        case <-readTicker.C:
            err = xml.Unmarshal(body, &m)
            if err != nil 
                log.Println(err.Error())
            
        
    

它所做的只是一遍又一遍地重复解码一个 XML 文件。我们的盒子表现出相同的症状:二进制文件的内存使用量无限制地增长,直到盒子开始交换。

我们还在上面的脚本中添加了一些 20 秒后触发的分析代码,并从pproftop100 得到以下内容:

(pprof) top100
Total: 56.0 MB
    55.0  98.2%  98.2%     55.0  98.2% encoding/xml.copyValue
     1.0   1.8% 100.0%      1.0   1.8% cnew
     0.0   0.0% 100.0%      0.5   0.9% bytes.(*Buffer).WriteByte
     0.0   0.0% 100.0%      0.5   0.9% bytes.(*Buffer).grow
     0.0   0.0% 100.0%      0.5   0.9% bytes.makeSlice
     0.0   0.0% 100.0%     55.5  99.1% encoding/xml.(*Decoder).Decode
...

稍后运行此程序,在盒子内存不足之前,会产生更高的总数,但百分比几乎相同。任何人都可以帮助我们吗?我们缺少什么?

提前致谢!

【问题讨论】:

我已经多次看到这个奇怪的循环。不知道它来自哪里,但是那里的代码太多了。试试这个:play.golang.org/p/GFkmfn_CYV(也修复了你的内存问题) 谢谢!我以前没见过range ticker 【参考方案1】:

尝试每次打印出您的消息。它将继续将字段附加到原始结构上。

你需要用m = message在你做你需要做的事情后重置消息,清除它,否则它会继续增长。

【讨论】:

伟大的收获!我想知道这是错误还是期望的行为。在我看来像一个错误。 不,这是期望的行为。根据文档:“Unmarshal 通过扩展切片的长度并将元素映射到新创建的值,将 XML 元素映射到切片。”【参考方案2】:

我尚未对此进行测试,但您是否尝试在每次执行此操作时将 XML 解组为一个新变量?

据我所知,您是在指针中执行此操作,这可能会导致内存出现一些问题。

当然,我可能完全错了。

【讨论】:

以上是关于golang读取XML内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

Golang内存泄漏问题和处理方法

golang 切片中的内存泄漏

手撸golang GO与微服务 ChatServer之4 内存泄漏

排查内存泄漏最简单和直观的方法

怎么排查这些内存泄漏

前端vue项目内存泄漏排查总结