再測Golang JSON類庫

來源:互聯網
上載者:User

寫項目一直需要進行序列化,聽到了,也看到了很多同學老師對各個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 jsonbenchimport (    "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/opBenchmark_STD_Marshal2-4                   30000             49598 ns/opBenchmark_EASYJSON_STD_Marshal1-4          30000             45778 ns/opBenchmark_EASYJSON_STD_Marshal2-4          30000             50440 ns/opBenchmark_EASYJSON_Marshal1-4             100000             14387 ns/opBenchmark_EASYJSON_Marshal2-4             100000             16009 ns/opBenchmark_ITERATOR_Marshal1-4             100000             14899 ns/opBenchmark_ITERATOR_Marshal2-4             100000             21629 ns/opBenchmark_FFJSON_Marshal1-4                50000             31633 ns/opBenchmark_FFJSON_Marshal2-4                30000             51668 ns/opBenchmark_GOB_Encode1-4                    20000             97099 ns/opBenchmark_GOB_Encode2-4                    10000            153158 ns/opBenchmark_STD_Unmarshal1-4                 20000             89211 ns/opBenchmark_STD_Unmarshal2-4                 20000             76442 ns/opBenchmark_EASYJSON_STD_Unmarshal1-4        30000             57695 ns/opBenchmark_EASYJSON_STD_Unmarshal2-4        20000             66269 ns/opBenchmark_EASYJSON_Unmarshal1-4           100000             19028 ns/opBenchmark_EASYJSON_Unmarshal2-4           100000             22035 ns/opBenchmark_ITERATOR_UnMarshal1-4            50000             35942 ns/opBenchmark_ITERATOR_UnMarshal2-4            50000             36462 ns/opBenchmark_FFJSON_UnMarshal1-4              20000             80290 ns/opBenchmark_FFJSON_UnMarshal2-4              20000             78431 ns/opBenchmark_GOB_Decode1-4                     3000            377698 ns/opBenchmark_GOB_Decode2-4                     3000            463472 ns/opPASSok      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與標準庫結合。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.