我正在使用Go,Revel WAF和Redis。
我必须在Redis中存储大的json数据(可能是20MB)。
json.Unmarshal()
大约需要5秒钟。什么是更好的方法呢?
我尝试过JsonLib,编码/ json,ffjson,megajson,但没有一个足够快。
我考虑过使用groupcache,但是Json会实时更新。
这是示例代码:
package main
import (
"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!!!
}
答案 0 :(得分:8)
解析大型JSON数据似乎确实比它应该慢。确定原因并向Go作者提交补丁是值得的。
与此同时,如果您可以避免使用JSON并使用二进制格式,那么您不仅可以避免此问题;您还将获得代码现在花费时间将数字的ASCII十进制表示解析为其二进制IEEE 754等效值的时间(并且在执行此操作时可能会引入舍入错误。)
如果发件人和收件人都是用Go编写的,我建议使用Go的二进制格式:gob。
进行快速测试,生成一个包含2000个条目的地图,每个条目包含1050个简单的浮点数,为我提供20 MB的JSON,在我的机器上解析需要1.16秒。
对于这些快速基准测试,我会充分利用三次运行,但我确保只测量实际的解析时间,在Unmarshal调用之前使用t0 := time.Now()
并在其后打印time.Now().Sub(t0)
。
使用GOB,相同的地图会生成18 MB的数据,需要115 ms才能解析:
十分之一的时间。
您的结果将根据您拥有的实际浮动数量而有所不同。如果你的浮点数有很多有效数字,值得他们的float64表示,那么20 MB的JSON将包含比我的200万浮点数少得多的数据。在这种情况下,JSON和GOB之间的区别将更加明显。
BTW,这证明了问题确实存在于JSON解析器中,而不是要解析的数据量,也不是要创建的内存结构(因为两个测试都在解析~20 MB的数据并重新创建相同的切片浮动。)用JSON中的字符串替换所有浮点数给出了1.02秒的解析时间,确认从字符串表示到二进制浮点数的转换确实需要一定的时间(与仅移动字节相比)但不是主要的罪魁祸首如果发件人和解析器都不是Go,或者你想要比GOB更进一步挤出性能,你应该使用你自己的自定义二进制格式,使用Protocol Buffers或手动使用" encoding / binary& #34;和朋友们。
答案 1 :(得分:0)
试试fastjson。它针对速度进行了优化,与标准encoding/json
相比,通常可以更快地解析JSON。此外,fastjson
不需要遵循JSON模式的结构 - 单个解析器可以使用不同的模式解析多个JSON。
答案 2 :(得分:0)
与官方版本相比,我的解码速度提高了2倍,更多的好处是jsoniter的API与encoding / json兼容。