2016-05-24 35 views
0

Go標準lib,Json序列化性能問題... JSON比XML和GOB慢,而json大小小於xml文件大小?golang json/gob/xml中的序列化性能

請幫忙指出什麼錯誤?

[email protected]:~/go/projects/wiki$ go run encoding.go 
2016/05/24 00:52:16 Serialization by JSON elapsed: 2152195 us 
2016/05/24 00:52:16 students.json 19177782 
2016/05/24 00:52:17 Serialization by GOB elapsed: 748867 us 
2016/05/24 00:52:17 students.gob 9305166 
2016/05/24 00:52:18 Serialization by XML elapsed: 1507397 us 
2016/05/24 00:52:18 students.xml 26177780 

[email protected]:~/go/projects/wiki$ go run encoding.go 
2016/05/24 00:52:32 Serialization by JSON elapsed: 1388153 us 
2016/05/24 00:52:32 students.json 19177782 
2016/05/24 00:52:33 Serialization by GOB elapsed: 502814 us 
2016/05/24 00:52:33 students.gob 9305166 
2016/05/24 00:52:34 Serialization by XML elapsed: 897859 us 
2016/05/24 00:52:34 students.xml 26177780 

[email protected]:~/go/projects/wiki$ go run encoding.go 
2016/05/24 00:52:41 Serialization by JSON elapsed: 1290359 us 
2016/05/24 00:52:41 students.json 19177782 
2016/05/24 00:52:42 Serialization by GOB elapsed: 434203 us 
2016/05/24 00:52:42 students.gob 9305166 
2016/05/24 00:52:42 Serialization by XML elapsed: 862379 us 
2016/05/24 00:52:42 students.xml 26177780 

代碼:

package main 


import (
     "log" 
     "encoding/json" 
     "encoding/gob" 
     "encoding/xml" 
     "math/rand" 
     "strconv" 
     "os" 
     "time" 
) 



const (
     Male=iota 
     Female 
     Unknown 

     ALL=100000 
) 

type Person struct { 
     Name string 
     Id  string 
     Age  int 
     Gender int 
} 
type Student struct { 
     Person Person 
     Grade int 
     Class string 
     Teacher Person 
} 

func (s Student) String() string{ 
     v,err:=json.Marshal(s) 
     if err!=nil { 
       log.Fatal("Marshal failed",s) 
     } 
     return string(v) 

} 

var students []Student 
func init(){ 
     students=make([]Student,ALL) 
     for i:=0;i<ALL;i++ { 
       students[i].Grade=rand.Intn(5) 
       students[i].Class=strconv.Itoa(students[i].Grade)+",class"+strconv.Itoa(rand.Intn(10)) 
       students[i].Person.Name="Student "+strconv.Itoa(i) 
       students[i].Person.Id="110"+strconv.Itoa(rand.Intn(10)) 
       students[i].Person.Age=10+rand.Intn(10) 
       students[i].Person.Gender=rand.Intn(3) 
       students[i].Teacher.Id="22001154365151344"+strconv.Itoa(rand.Intn(10)) 
       students[i].Teacher.Name="Teacher "+strconv.Itoa(i) 
       students[i].Teacher.Age=40+rand.Intn(10) 
       students[i].Teacher.Gender=rand.Intn(3) 
     } 

} 

func toJsonFile(){ 
     f,err:=os.OpenFile("students.json",os.O_RDWR ,0600) 
     if err!=nil { 
       log.Fatal("Can't open students.json "+ err.Error()) 
     } 
     defer f.Close() 
     en:=json.NewEncoder(f) 
     err=en.Encode(students) 
     if err!=nil { 

       log.Fatal(err) 
     } 

} 

func loadJsonFile(){ 
     f,err:=os.Open("students.json") 
     if err!=nil { 
       log.Fatal(err) 
     } 
     defer f.Close() 
     dec:=json.NewDecoder(f) 
     ss:=make([]Student,ALL) 
     err=dec.Decode(&ss) 
     if err!=nil { 

       log.Fatal(err) 
     } 
//  log.Println(ss) 
} 



func toGobFile(){ 
     f,err:=os.OpenFile("students.gob",os.O_RDWR ,0600) 
     if err!=nil { 
       log.Fatal("Can't open students.gob "+ err.Error()) 
     } 
     defer f.Close() 
     en:=gob.NewEncoder(f) 
     err=en.Encode(students) 
     if err!=nil { 

       log.Fatal(err) 
     } 

} 

func loadGobFile(){ 
     f,err:=os.Open("students.gob") 
     if err!=nil { 
       log.Fatal(err) 
     } 
     defer f.Close() 
     dec:=gob.NewDecoder(f) 
     ss:=make([]Student,ALL) 
     err=dec.Decode(&ss) 
     if err!=nil { 

       log.Fatal(err) 
     } 
//  log.Println(ss) 
} 



func toXmlFile(){ 
     f,err:=os.OpenFile("students.xml",os.O_RDWR ,0600) 
     if err!=nil { 
       log.Fatal(err.Error()) 
     } 
     defer f.Close() 
     en:=xml.NewEncoder(f) 
     err=en.Encode(students) 
     if err!=nil { 

       log.Fatal(err) 
     } 

} 
func loadXmlFile(){ 
     f,err:=os.Open("students.xml") 
     if err!=nil { 
       log.Fatal(err) 
     } 
     defer f.Close() 
     dec:=xml.NewDecoder(f) 
     ss:=make([]Student,ALL) 
     err=dec.Decode(&ss) 
     if err!=nil { 

       log.Fatal(err) 
     } 
//  log.Println(ss) 
} 




func main(){ 
     start:=time.Now() 
     toJsonFile() 
     loadJsonFile() 
     end:=time.Now() 

     log.Printf("Serialization by JSON elapsed: %d us",end.Sub(start)/1000) 

     fi,err:=os.Stat("students.json") 
     if err!=nil { 
       log.Fatal(err) 
     } 
     log.Println(fi.Name(), fi.Size()) 



     start=time.Now() 
     toGobFile() 
     loadGobFile() 
     end=time.Now() 


     log.Printf("Serialization by GOB elapsed: %d us",end.Sub(start)/1000) 

     fi,err=os.Stat("students.gob") 
     if err!=nil { 
       log.Fatal(err) 
     } 
     log.Println(fi.Name(), fi.Size()) 

     start=time.Now() 
     toXmlFile() 
     loadXmlFile() 
     end=time.Now() 


     log.Printf("Serialization by XML elapsed: %d us",end.Sub(start)/1000) 

     fi,err=os.Stat("students.xml") 
     if err!=nil { 
       log.Fatal(err) 
     } 
     log.Println(fi.Name(), fi.Size()) 

} 
+0

Go的哪個版本? – OneOfOne

+0

go版本go1。6 linux/amd64 – zhannk

+1

如果您想測量(反)序列化的速度,請勿寫入磁盤。除此之外:什麼是問題? – Volker

回答

0

默認JSON編碼器/解碼器執行大量的反射。查看https://github.com/pquerna/ffjson以瞭解更換代碼的情況,該代碼可生成用於大幅改進性能的代碼。

0

正如您所報告的,您的基準測試具有很多內部運行可變性。這使得難以推理該問題。我們真正想要的是一個總是給出相同結果的基準,無論我們在哪一天運行它。

我修改您的基準略微這樣更容易可靠地重現的結果:1。 我序列化的數據存儲(以字節片[]byte), 2.我避免溢出處理器的數據緩存(即,使用少量數據)。

在Go中有一個標準的寫入基準的方法,以獲得更多可重複的結果(https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go),但在這種情況下,我沒有發現它是必要的。

見我在https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/extra/golang/serialization

在我的測試服務器代碼(SKYLAKE微架構處理器,配置進行測試,在平坦的3.4 GHz的運行,與去1.7),我得到...

2016/12/22 09:55:54 Serialization by JSON elapsed: 599 us 2016/12/22 09:55:54 serialized size in bytes: 18781 2016/12/22 09:55:54 Serialization by GOB elapsed: 230 us 2016/12/22 09:55:54 serialized size in bytes: 9066 2016/12/22 09:55:54 Serialization by XML elapsed: 2404 us 2016/12/22 09:55:54 serialized size in bytes: 25780

正如你可以看到我的結果一樣,JSON比XML稍大一點(30%),而GOB要小得多。這與你的結果一致。仍然與您的結果一致,GOB比XML和JSON快得多。

但是,JSON序列化比XML序列化要快得多(因數爲4)。 GOB的速度是JSON的兩倍。

你會在自己的硬件上得到不同的結果,但我懷疑你會得到相當一致的數字(小運行間變化),特別是如果你禁用CPU功能,如TurboBoost。

如果我們實際序列化到磁盤或使用大量數據blob會發生什麼?它不會改變性能順序,因爲GOB越來越小,JSON在數據大小和處理大小方面處於中間位置,並且XML更加臃腫,處理速度更慢。

所以我認爲我們可以有把握地得出結論,我們有以下...

  1. GOB是更小,更快。

  2. JSON小而快。

  3. XML很大很慢。