亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go JSON 解碼非常慢。什么是更好的方法呢?

Go JSON 解碼非常慢。什么是更好的方法呢?

Go
慕田峪7331174 2021-09-27 10:56:13
我正在使用 Go、Revel WAF 和 Redis。我必須在 Redis 中存儲大型 json 數據(可能是 20MB)。json.Unmarshal()大約需要 5 秒鐘。什么是更好的方法呢?我嘗試了 JsonLib、encode/json、ffjson、megajson,但它們都不夠快。想過用groupcache,但是Json是實時更新的。這是示例代碼:package mainimport ( "github.com/garyburd/redigo/redis"  json "github.com/pquerna/ffjson/ffjson")func main() {  c, err := redis.Dial("tcp", ":6379")  defer c.Close()  pointTable, err := redis.String(c.Do("GET", "data"))  var hashPoint map[string][]float64  json.Unmarshal([]byte(pointTable), &hashPoint) //Problem!!!}
查看完整描述

3 回答

?
呼喚遠方

TA貢獻1856條經驗 獲得超11個贊

解析大型 JSON 數據似乎比它應該的要慢。查明原因并向 Go 作者提交補丁是值得的。

同時,如果你能避免使用JSON并使用二進制格式,你不僅可以避免這個問題;您還將獲得代碼現在花費的時間將數字的 ASCII 十進制表示解析為它們的二進制 IEEE 754 等效項(并且在這樣做時可能會引入舍入錯誤。)

如果您的發送方和接收方都是用 Go 編寫的,我建議使用 Go 的二進制格式:gob

做一個快速測試,生成一個包含 2000 個條目的地圖,每個條目有 1050 個簡單浮點數,給我 20 MB 的 JSON,在我的機器上解析需要 1.16 秒。

對于這些快速基準測試,我采用了三個運行中的最佳值,但我確保只測量實際解析時間,t0 := time.Now()在 Unmarshal 調用之前和time.Now().Sub(t0)之后打印。

使用 GOB,相同的地圖產生 18 MB 的數據,解析需要 115 毫秒:
時間的十分之一

您的結果將根據您在那里擁有的實際浮點數而有所不同。如果你的浮點數有很多有效數字,值得他們用 float64 表示,那么 20 MB 的 JSON 將比我的 200 萬個浮點數少得多。在這種情況下,JSON 和 GOB 之間的區別將變得更加明顯。

順便說一句,這證明問題確實在于 JSON 解析器,而不是要解析的數據量,也不在于要創建的內存結構(因為兩個測試都在解析 ~ 20 MB 的數據并重新創建相同的浮點數切片。)用 JSON 中的字符串替換所有浮點數給了我 1.02 秒的解析時間,確認從字符串表示到二進制浮點數的轉換確實需要一定時間(與僅移動字節相比)但不是主要的罪魁禍首。

如果發送方和解析器都不是 Go,或者如果你想比 GOB 更進一步地壓縮性能,你應該使用你自己定制的二進制格式,要么使用協議緩沖區,要么手動使用“編碼/二進制”和朋友。


查看完整回答
反對 回復 2021-09-27
?
料青山看我應如是

TA貢獻1772條經驗 獲得超8個贊

試試fastjson。它針對速度進行了優化,并且與標準encoding/json. 此外,fastjson不需要遵循 JSON 模式的結構 - 單個解析器可以解析具有不同模式的多個 JSON。


查看完整回答
反對 回復 2021-09-27
  • 3 回答
  • 0 關注
  • 467 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號