我有一个100 GB的XML文件,并在下面的代码中使用SAX方法解析它
file, err := os.Open(filename)
handle(err)
defer file.Close()
buffer := bufio.NewReaderSize(file, 1024*1024*256) // 33554432
decoder := xml.NewDecoder(buffer)
for {
t, _ := decoder.Token()
if t == nil {
break
}
switch se := t.(type) {
case xml.StartElement:
if se.Name.Local == "House" {
house := House{}
err := decoder.DecodeElement(&house, &se)
handle(err)
}
}
}
字符串
但是golang的工作速度非常慢,它似乎是由执行时间和磁盘使用。我的硬盘能够读取数据的速度约100-120 MB/s,但golang只使用10-13 MB/s.
为了实验,我用C#重写了以下代码:
using (XmlReader reader = XmlReader.Create(filename)
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name == "House")
{
//Code
}
break;
}
}
}
型
我得到了完整的硬盘加载,C#读取数据与100-110 MB/s的速度。执行时间大约降低10倍。
如何使用golang提高XML解析性能?
2条答案
按热度按时间6l7fqoea1#
这5件事可以帮助使用
encoding/xml
库提高速度:1.使用定义明确的结构
xml.Unmarshaller
d.DecodeElement(&foo, &token)
替换为foo.UnmarshallXML(d, &token)
d.RawToken()
代替d.Token()
d.Skip()
,则使用d.RawToken()
重新实现它在我的特定用例上,我减少了40%的时间和分配,代价是更多的代码,样板文件,以及潜在的更糟糕的极端情况处理,但我的输入相当一致,但这还不够。
字符串
在我的实验中,lack of memoizing issue是XML解析器上大量时间/分配的原因,这会显著减慢速度,主要是因为Go通过值复制。
kwvwclae2#
回答您的问题 “如何使用golang提高xml解析性能?“
使用常见的
xml.NewDecoder
/decoder.Token
,我在本地看到50 MB/s。通过使用https://github.com/tamerh/xml-stream-parser,我能够将解析速度提高一倍。为了进行测试,我使用了https://archive.org/details/stackexchange存档torrent中的
Posts.xml
(68 GB)。字符串
这将输出如下内容:
型
唯一需要注意的是,这并不能方便地解组为结构。
正如https://github.com/golang/go/issues/21823中所讨论的,速度似乎是Golang中XML实现的普遍问题,需要重写/重新考虑标准库的这一部分。