登录
首页 >  Golang >  Go问答

在 Go 中加速 JSON 解析

来源:Golang技术栈

时间:2023-04-29 16:57:17 398浏览 收藏

在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是Golang学习者,那么本文《在 Go 中加速 JSON 解析》就很适合你!本篇内容主要包括在 Go 中加速 JSON 解析,希望对大家的知识积累有所帮助,助力实战开发!

问题内容

我们有事务日志文件,其中每个事务都是 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 代码中的不同属性,看看是否有一个特别成问题。没有一个对性能产生明显影响。关于提高性能的任何建议,或者这仅仅是编译语言对其他语言没有实质性好处的情况?

正确答案

尝试使用类型来删除所有这些不必要的赋值和类型断言;

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)

我不会对此进行测试以确保它优于您的代码,但我敢打赌它会大大提高。试一试,请告诉我。

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>