Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json decode is slower than go! #12833

Closed
zhuxiujia opened this issue Dec 7, 2019 · 9 comments
Closed

json decode is slower than go! #12833

zhuxiujia opened this issue Dec 7, 2019 · 9 comments

Comments

@zhuxiujia
Copy link

zhuxiujia commented Dec 7, 2019

Faster than Java, but seven times slower than golang

Nim Code

import os
import json
import util/benchmark_util

proc getNano() :float64=
    return cpuTime()*1000000000

proc benchmark_item(count_index:int64,count_time:int64,total:float64,callback:proc():void): void =
    echo "bench:",count_index
    let cpuStartTime =  getNano()
    for index in 1..total.toBiggestInt():
         callback()
    var useTime=getNano() - cpuStartTime
    var ns_op=useTime/total
    echo "Time taken: ", useTime,"ns"
    echo ">      number:",total,"      bench: ",ns_op,"  ns/op"

# Statistics execution time
proc benchmark(count_time:int64,total:float64,callback:proc():void) =
    for count_index in 1..count_time:
       benchmark_item(count_index,count_time,total,callback)


type User = object
            id: string
            name: string
            version: int

# echo(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>now  start runing")


proc test(): void =
      let js="""{"id": "","name": "","version": 0}"""
      let jsonNode = parseJson(js)
      let u=to(jsonNode, User)
      #echo u

benchmark(1,3000000,test)
echo "done"

golang Code

type User struct {
	id string
	name string
	version int32
}
func BenchmarkJSON(b *testing.B) {
	b.StopTimer()
	var u=User{
		id:"",
		name:"",
		version:0,
	}
	var v,_=json.Marshal(u)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		var u=User{}
		 e:=json.Unmarshal(v,&u)
		 if e!=nil{
		 	panic(e)
		 }
	}
}

Current Output

nim output

nim c  -d:release -r main.nim
number:3000000.0      bench: 1568.333333333333  ns/op [Windows: amd64]

go output

nim c  -d:release -r main.nim
number:3000000.0      bench: 205  ns/op   [Windows: amd64]

Expected Output

nim c  -d:release -r main.nim
golang:   number:3000000.0      bench: 205  ns/op   [Windows: amd64]
nim:        number:3000000.0      bench: 1568.333333333333  ns/op   [Windows: amd64]

Possible Solution

JSON standard library optimizes performance

$ nim -v
Nim Compiler Version 1.0.4 [Windows: amd64]
@ghost
Copy link

ghost commented Dec 7, 2019

What about using -d:danger instead of -d:release? Also, did you try packedjson (or other nimble JSON decode libs)? And does that JSON performance affect your actual app (not some microbenchmarks)?

@zhuxiujia
Copy link
Author

zhuxiujia commented Dec 7, 2019

What about using -d:danger instead of -d:release? Also, did you try packedjson (or other nimble JSON decode libs)? And does that JSON performance affect your actual app (not some microbenchmarks)?

use -d:danger it also slow.... my

number:3000000.0 bench: 1390.666666666667 ns/op

and .... My program requires high JSON parsing

Why is compiling to Clang much slower than go??

@Araq
Copy link
Member

Araq commented Dec 7, 2019

Dunno, probably you measure different things.

@zhuxiujia
Copy link
Author

zhuxiujia commented Dec 7, 2019

Dunno, probably you measure different things.

use packedjson

number:3000000.0 bench: 947.6666666666666 ns/op

and .... Faster than Java, but seven times slower than golang

@Araq
Copy link
Member

Araq commented Dec 7, 2019

It's not surprising Go's implementation is faster, they deserialize directly into the struct
which we could also do but don't.

One problem is that Go's implementation is also full of stuff where I can trigger pathological behaviour, you can't just "write a fast JSON library". what if the JSON has a 10GB string literal inside? what if it has object fields with 1000 entries?

JSON is used for everything and so you need to protect against so many different things and then once you did, it's kinda slow for the general case.

Having said that, we'll of course improve the performance further.

@zhuxiujia
Copy link
Author

It's not surprising Go's implementation is faster, they deserialize directly into the struct
which we could also do but don't.

One problem is that Go's implementation is also full of stuff where I can trigger pathological behaviour, you can't just "write a fast JSON library". what if the JSON has a 10GB string literal inside? what if it has object fields with 1000 entries?

JSON is used for everything and so you need to protect against so many different things and then once you did, it's kinda slow for the general case.

Having said that, we'll of course improve the performance further.

If it's fast, it's a great programming language

@ringabout

This comment has been minimized.

@disruptek
Copy link
Contributor

Jason doesn't deserialize (yet).

@timotheecour timotheecour changed the title json decode is slow than go! json decode is slower than go! Nov 13, 2020
@FedericoCeratto
Copy link
Member

Related to #3809 and #12152

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants