再测Golang JSON类库

写项目一直需要进行序列化,听到了,也看到了很多同学老师对各个golang的json库进行测评。那本人为什么还要继续进行这一次测评呢?
因为实践过的知识最有说服力,也是属于自己的,我也希望看到本博文的同学老师可以修改和执行测评的代码执行一遍,我相信会有不一定的体会。
本次测评我选择了类库有:

类库

序号 类库 地址 备注
1 encoding/json Golan
2 easyjson github.com/mailru/easyjson
3 ffjson github.com/mailru/easyjson
4 iterator/json github.com/json-iterator/go

主要是针对上述的类型进行,本人采用了对不同的类库使用不同的结构体(仅仅是结构体名称不同,字段顺序和类型一样)。

环境

环境为MacBook Pro(Core i5处理器/8GB内存)go1.8.3 darwin/amd64

代码

bench代码如下:

package jsonbench

import (
    "encoding/gob"

    "encoding/json"
    "github.com/json-iterator/go"
    "github.com/mailru/easyjson"
    "github.com/pquerna/ffjson/ffjson"
    "testing"
)

var (
    iterator = jsoniter.ConfigCompatibleWithStandardLibrary
    // easyjson
    as = AgentService{
        ServiceName:    "kaleidoscope_api",
        Version:        "1517558949087295000_1298498081",
        ServiceId:      "kaleidoscope_kaleidoscope.dev.igetget.com_v1.2",
        Address:        "kaleidoscope.dev.igetget.com",
        Port:           80,
        Metadata:       map[string]string{},
        ConnectTimeOut: 1000,
        ConnectType:    "LONG",
        ReadTimeOut:    1000,
        WriteTimeOut:   1000,
        Protocol:       "HTTP",
        Balance:        "Random",
        Idcs:           "hu,hd,hn",
        Converter:      "json",
        Retry:          3,
    }
    service            = as.ToService()
    asBytes, _         = json.Marshal(as)
    serviceBytes, _    = json.Marshal(service)
    asStr              = string(asBytes)
    serviceStr         = string(serviceBytes)
    asGonBytes, _      = GobEncode(as)
    serviceGonBytes, _ = GobEncode(service)
    // std
    asstd = AgentServiceSTD{
        ServiceName:    "kaleidoscope_api",
        Version:        "1517558949087295000_1298498081",
        ServiceId:      "kaleidoscope_kaleidoscope.dev.igetget.com_v1.2",
        Address:        "kaleidoscope.dev.igetget.com",
        Port:           80,
        Metadata:       map[string]string{},
        ConnectTimeOut: 1000,
        ConnectType:    "LONG",
        ReadTimeOut:    1000,
        WriteTimeOut:   1000,
        Protocol:       "HTTP",
        Balance:        "Random",
        Idcs:           "hu,hd,hn",
        Converter:      "json",
        Retry:          3,
    }
    servicestd            = asstd.ToServiceSTD()
    asBytesstd, _         = json.Marshal(asstd)
    serviceBytesstd, _    = json.Marshal(servicestd)
    asStrstd              = string(asBytesstd)
    serviceStrstd         = string(serviceBytesstd)
    asGonBytesstd, _      = GobEncode(asstd)
    serviceGonBytesstd, _ = GobEncode(servicestd)
)

// go test -bench=".*"
func init() {
    gob.Register(AgentService{})
}

func Benchmark_STD_Marshal1(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := json.Marshal(asstd)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_STD_Marshal2(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := json.Marshal(servicestd)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_STD_Marshal1(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := json.Marshal(as)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_STD_Marshal2(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := json.Marshal(service)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_Marshal1(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := easyjson.Marshal(as)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_Marshal2(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := easyjson.Marshal(service)
        if err != nil {
            b.Error(err)
        }
    }
}

//
func Benchmark_ITERATOR_Marshal1(b *testing.B) {

    for i := 0; i < b.N*10; i++ {
        _, err := iterator.Marshal(asstd)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_ITERATOR_Marshal2(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := iterator.Marshal(servicestd)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_FFJSON_Marshal1(b *testing.B) {

    for i := 0; i < b.N*10; i++ {
        _, err := ffjson.Marshal(asstd)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_FFJSON_Marshal2(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        _, err := ffjson.Marshal(servicestd)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_GOB_Encode1(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        GobEncode(as)
    }
}

func Benchmark_GOB_Encode2(b *testing.B) {
    for i := 0; i < b.N*10; i++ {
        GobEncode(service)
    }
}

func Benchmark_STD_Unmarshal1(b *testing.B) {
    tmp := AgentServiceSTD{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := json.Unmarshal(asBytesstd, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_STD_Unmarshal2(b *testing.B) {
    tmp := ServiceSTD{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := json.Unmarshal(serviceBytesstd, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_STD_Unmarshal1(b *testing.B) {
    tmp := AgentService{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := json.Unmarshal(asBytes, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_STD_Unmarshal2(b *testing.B) {
    tmp := Service{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := json.Unmarshal(serviceBytes, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_Unmarshal1(b *testing.B) {
    tmp := AgentService{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := easyjson.Unmarshal(asBytes, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_EASYJSON_Unmarshal2(b *testing.B) {
    tmp := Service{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := easyjson.Unmarshal(serviceBytes, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_ITERATOR_UnMarshal1(b *testing.B) {

    tmp := ServiceSTD{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := iterator.Unmarshal(serviceBytesstd, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_ITERATOR_UnMarshal2(b *testing.B) {
    tmp := ServiceSTD{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := iterator.Unmarshal(serviceBytesstd, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_FFJSON_UnMarshal1(b *testing.B) {

    tmp := ServiceSTD{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := ffjson.Unmarshal(serviceBytesstd, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_FFJSON_UnMarshal2(b *testing.B) {
    tmp := ServiceSTD{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        err := ffjson.Unmarshal(serviceBytesstd, &tmp)
        if err != nil {
            b.Error(err)
        }
    }
}

func Benchmark_GOB_Decode1(b *testing.B) {
    tmp := AgentService{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        GobDecode(asGonBytes, &tmp)
    }
}

func Benchmark_GOB_Decode2(b *testing.B) {
    tmp := Service{}
    for i := 0; i < b.N*10; i++ {
        as.Port = i
        GobDecode(serviceGonBytes, &tmp)
    }
}

执行命令:

go test -bench=".*"

测评结果;

$ go test -bench=".*"
Benchmark_STD_Marshal1-4                   50000             31224 ns/op
Benchmark_STD_Marshal2-4                   30000             49598 ns/op
Benchmark_EASYJSON_STD_Marshal1-4          30000             45778 ns/op
Benchmark_EASYJSON_STD_Marshal2-4          30000             50440 ns/op
Benchmark_EASYJSON_Marshal1-4             100000             14387 ns/op
Benchmark_EASYJSON_Marshal2-4             100000             16009 ns/op
Benchmark_ITERATOR_Marshal1-4             100000             14899 ns/op
Benchmark_ITERATOR_Marshal2-4             100000             21629 ns/op
Benchmark_FFJSON_Marshal1-4                50000             31633 ns/op
Benchmark_FFJSON_Marshal2-4                30000             51668 ns/op
Benchmark_GOB_Encode1-4                    20000             97099 ns/op
Benchmark_GOB_Encode2-4                    10000            153158 ns/op
Benchmark_STD_Unmarshal1-4                 20000             89211 ns/op
Benchmark_STD_Unmarshal2-4                 20000             76442 ns/op
Benchmark_EASYJSON_STD_Unmarshal1-4        30000             57695 ns/op
Benchmark_EASYJSON_STD_Unmarshal2-4        20000             66269 ns/op
Benchmark_EASYJSON_Unmarshal1-4           100000             19028 ns/op
Benchmark_EASYJSON_Unmarshal2-4           100000             22035 ns/op
Benchmark_ITERATOR_UnMarshal1-4            50000             35942 ns/op
Benchmark_ITERATOR_UnMarshal2-4            50000             36462 ns/op
Benchmark_FFJSON_UnMarshal1-4              20000             80290 ns/op
Benchmark_FFJSON_UnMarshal2-4              20000             78431 ns/op
Benchmark_GOB_Decode1-4                     3000            377698 ns/op
Benchmark_GOB_Decode2-4                     3000            463472 ns/op
PASS
ok      studygo/jsonbench       49.174s

结论

  1. 哪一个类库最快?
    答:是测评类库中最快的。速度:easyjson => iterator => encoding/json => ffjson
  2. 是否存在坑?
    答:easyjson有一个坑,从代码中可以看到Benchmark_EASYJSON_STD_*的方法,是因为easyjson生成的代码中已经包含了MarshalJSONUnmarshalJSON方法,那么只要对这些结构体执行json.marshalJSONjson.UnmarshalJSON都会默认调用easyjson生成的方法。本人运行多次,都会发现调用easyjson生成的MarshalJSON方法比标准库中的慢一些达到50%左右,但是调用easyjson生成的UnmarshalJSON比标准库的快一些大概20%。
  3. 如何选择?
    答:easyjson速度虽然比较快,但也是存在一些不适合的场景,比如如果需要对interface接口进行序列化时候。所以建议采用easyjson与标准库结合。

原文地址:http://blog.51cto.com/qiangmzsx/2070603

时间: 2024-10-04 11:50:37

再测Golang JSON类库的相关文章

两款JSON类库Jackson与JSON-lib的性能对比(新增第三款测试)

本篇文章主要介绍了"两款JSON类库Jackson与JSON-lib的性能对比(新增第三款测试)",主要涉及到两款JSON类库Jackson与JSON-lib的性能对比(新增第三款测试)方面的内容,对于两款JSON类库Jackson与JSON-lib的性能对比(新增第三款测试)感兴趣的同学可以参考一下. 近日做一些性能优化工作,在挑选JSON类库时,发现除了一般常用的JSON-lib外,还有一款号称性能最快的JSON处理器Jackson,于是用上了刚学会的JMeter,对这两个类库进行

golang json处理struct未导出成员

我们用golang的json来marshal一个结构体的时候,结构体的未导出的成员将无法被json访问,也就是不会出现json编码的结果里(也就是小写的成员没法导出) 这个是由于技术的上问题引起的:golang的结构体里的成员的名字如果以小写字母开头,那么其他的包是无法访问的,也就是json无法访问我们的结构体里小写字母开头的成员 这个可以有两种方法解决 1. struct的成员用大写开头,然后加tag 2. 实现json.Marshaler接口 第一种方法比较常见这儿就不详细展开了 第二种方法

golang json处理

序列化: 1)简单的数据结构: package main import ( "encoding/json" "fmt" "reflect" ) type School struct { Name string `json:"name"` Location string `json:"location"` } func main() { school := School{ Name: "某某学校&q

JSON类库Jackson与JSON-lib性能对比[转]

Jackson:http://jackson.codehaus.org/ JSON-lib:http://json-lib.sourceforge.net/ Gson:http://code.google.com/p/google-gson/ 测试环境: 1.工作电脑:Intel双核E8400 共6GHz,内存4GB,WinXP 2.JSON-lib用最新的JDK15,GSON版本是最新的v1.4,Jackson也是最新的v1.5.5,JDK-v1.6.0_20,JMeter-v2.4 3.测试

golang json操作

ackage main import ( "encoding/json" "fmt" "os" ) type ConfigStruct struct { Host string `json:"host"` Port int `json:"port"` AnalyticsFile string `json:"analytics_file"` StaticFileVersion int `j

golang json

package main import ( "encoding/json" "fmt" "os" ) type ConfigStruct struct { Expires_in     string `json:"expires_in"` Refresh_token  string `json:"refresh_token"` Access_token   string `json:"access

golang JSON webservice - nginx load balance

func main() { http.HandleFunc("/api", apiHandler) http.HandleFunc("/query/main", mainHandler) http.HandleFunc("/query/show", showHandler) http.HandleFunc("/", mainHandler) http.ListenAndServe(":8081", nil)

golang json 编码解码

golang  "encoding/json"包实现了json对象的编解码 一.编码 func Marshal(v interface{}) ([]byte, error) Marshal函数使用下面的基于类型的默认编码格式: 布尔类型编码为json布尔类型. 浮点数.整数和Number类型的值编码为json数字类型. 字符串编码为json字符串.角括号"<"和">"会转义为"\u003c"和"\u003

golang json用法讲解

简介 json格式可以算我们日常最常用的序列化格式之一了,Go语言作为一个由Google开发,号称互联网的C语言的语言,自然也对JSON格式支持很好.但是Go语言是个强类型语言,对格式要求极其严格而JSON格式虽然也有类型,但是并不稳定,Go语言在解析来源为非强类型语言时比如PHP等序列化的JSON时,经常遇到一些问题诸如字段类型变化导致无法正常解析的情况,导致服务不稳定.所以本篇的主要目的 就是挖掘Golang解析json的绝大部分能力 比较优雅的解决解析json时存在的各种问题 深入一下Go