我们有事务日志文件,其中每个事务都是JSON格式的单行。我们经常需要采集数据的选定部分,执行单次转换,并以特定格式将结果提供给另一个系统。我编写了一个Python脚本,可以根据需要执行此操作,但我希望Go会更快,并且会让我有机会开始学习Go。所以,我写了以下内容:
package main
import "encoding/json"
import "fmt"
import "time"
import "bufio"
import "os"
func main() {
sep := ","
reader := bufio.NewReader(os.Stdin)
for {
data, _ := reader.ReadString('\n')
byt := []byte(data)
var dat map[string]interface{}
if err := json.Unmarshal(byt, &dat); err != nil {
break
}
status := dat["status"].(string)
a_status := dat["a_status"].(string)
method := dat["method"].(string)
path := dat["path"].(string)
element_uid := dat["element_uid"].(string)
time_local := dat["time_local"].(string)
etime, _ := time.Parse("[02/Jan/2006:15:04:05 -0700]", time_local)
fmt.Print(status, sep, a_status, sep, method, sep, path, sep, element_uid, sep, etime.Unix(), "\n")
}
}
编译无怨无悔,但我对缺乏绩效改进感到惊讶。为了测试,我将2,000,000行日志放入tmpfs(以确保磁盘I / O不会受到限制)并比较脚本的两个版本。我的结果:
$ time cat /mnt/ramdisk/logfile | ./stdin_conv > /dev/null
real 0m51.995s
$ time cat /mnt/ramdisk/logfile | ./stdin_conv.py > /dev/null
real 0m52.471s
$ time cat /mnt/ramdisk/logfile > /dev/null
real 0m0.149s
怎样才能更快?我做了一些初步的努力。例如,ffjson项目建议创建静态函数,使反射变得不必要;然而,到目前为止我还没有让它工作,得到错误:
Error: Go Run Failed for: /tmp/ffjson-inception810284909.go
STDOUT:
STDERR:
/tmp/ffjson-inception810284909.go:9:2: import "json_parse" is a program, not an importable package
:
此外,我上面的内容不会被认为是静态类型的吗?可能不是 - 我正积极地躲在Go所关注的耳朵后面。我已经尝试选择性地禁用Go代码中的不同属性,以查看是否存在问题。没有人对表现产生明显影响。有关提高性能的任何建议,还是仅仅是编译语言没有其他实质性好处的情况?
答案 0 :(得分:5)
尝试使用类型删除所有这些不必要的赋值并键入断言;
type RenameMe struct {
Status string `json:"status"`
Astatus string `json:"a_status"`
Method string `json:"method"`
Path string `json:"path"`
ElementUid string `json:"element_uid"`
TimeLocal time.Time `json:"time_local"`
Etime time.Time // deal with this after the fact
}
data := &RenameMe{}
if err := json.Unmarshal(byt, data); err != nil {
break
}
data.Etime, _ := time.Parse("[02/Jan/2006:15:04:05 -0700]", time_local)
我不会对此进行测试,以确保它的性能优于您的代码,但我敢打赌它会大幅提升。试一试,请告诉我。
答案 1 :(得分:1)
http://jsoniter.com/声明自己是最快的json解析器,提供了golang和java实现。可以使用两种类型的api。并且预先注入的json对象定义是可选的。
答案 2 :(得分:0)
检查https://github.com/pquerna/ffjson
我看到标准库使用的标准json marshal / unmarshal方法有3倍的改进。它是通过重写源并消除反射的需要来实现的。