我出于性能原因考虑考虑将go用于我的未来项目,但是有一个很大的惊喜:go的运行时间为13.974427s,而python经过的时间仅为6.593028783798218s,不到一半!
XML文件大小超过300 MB。这是python的代码:
from lxml import objectify
import time
most = time.time()
root = objectify.parse(open(r"c:\temp\myfile.xml", 'rb')).getroot()
if hasattr(root, 'BaseData'):
if hasattr(root.BaseData, 'SzTTs'):
total_records = 0
for sztt in root.BaseData.SzTTs.sztt:
total_records += 1
print("total_records", total_records)
print("Time elapsed: ", time.time()-most)
Run Code Online (Sandbox Code Playgroud)
这是简化的go代码:
package main
// An example streaming XML parser.
import (
"encoding/xml"
"fmt"
"io"
"os"
"time"
)
var inputFile = "c:\\temp\\myfile.xml"
type SzTTs struct {
Sztt []sztt
}
type sztt struct {
}
func main() {
xmlFile, err := os.Open(inputFile)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer xmlFile.Close()
d := xml.NewDecoder(xmlFile)
total1 := 0
total2 := 0
start := time.Now()
for {
// Read tokens from the XML document in a stream.
t, err := d.Token()
// If we are at the end of the file, we are done
if t == nil || err == io.EOF {
fmt.Println("The end")
break
} else if err != nil {
log.Fatalf("Error decoding token: %s", err)
}
// Inspect the type of the token just read.
switch se := t.(type) {
case xml.StartElement:
if se.Name.Local == "SzTTs" {
var p SzTTs
// decode a whole chunk of following XML into the
// variable p which is a Page (se above)
if err = d.DecodeElement(&p, &se); err != nil {
log.Fatalf("Error decoding item: %s", err)
}
for i := range p.Sztt {
total1 = i
}
}
default:
}
}
fmt.Printf("Total sztt: %d \n", total1)
fmt.Printf("Elapsed time %s", time.Since(start))
}
Run Code Online (Sandbox Code Playgroud)
为什么会有如此大的差异?
扩展我的评论——这是预料之中的。
Goencoding/xml是用纯 Go 编写的,而lxml本质上是用 C 编写的。它使用 Cython,它从类似 Python 的 DSL 生成 C 代码。
恕我直言,2x 并不是一个巨大的性能差异,但如果性能的每一点下降对您都很重要,请考虑使用另一个 Go 包 - 一个包装优化的 C 实现的包。
例如,libxml(最流行的 C 实现之一)有几个包装器:
我预计这些会比encoding/xml.
Edid (2019-07-22):这个问题激励我写更多关于 Go 中的流式 XML 性能以及libxml SAX 接口的新包装器。
| 归档时间: |
|
| 查看次数: |
85 次 |
| 最近记录: |