jason icon indicating copy to clipboard operation
jason copied to clipboard

Provide "jason_native"

Open michalmuskala opened this issue 7 years ago • 7 comments

The idea would be to have a native implementation in either C or Rust. The package would be an optional dependency of jason. The Jason.encode/decode calls would automatically and seamlessly switch to the native code if available. This means a library author could just depend on jason and the developer of the final application could decide if they prefer the Elixir or native implementation.

Things that should be particularly nice for performance should be leveraging SIMD in escaping and some parts of parsing (similar to what is done in rapidjson).

michalmuskala avatar Nov 06 '17 15:11 michalmuskala

I think this is a great idea!

Having multiple Rust binaries for popular targets will be nice as well as using Rustler.

We could also just provide some sort of build step for those comfortable in the Rust ecosystem as well.

Now that serde is on stable we can (with confidence) push out stable/safe native perf for those that chose the alternative

selfup avatar Dec 25 '17 19:12 selfup

Yes, but we can't use serde directly - the problem is that it is not pre-emptive, so we can't use it with regular NIFs. It's true we have dirty schedulers, but I'm pretty sure using them in high concurrency situations for this could be even slower than the pure Elixir version (that statement is not confirmed by any experiments, though).

michalmuskala avatar Dec 25 '17 19:12 michalmuskala

Yea that makes sense. I wonder how this could otherwise be done 🤔

selfup avatar Dec 25 '17 20:12 selfup

The easiest way would be to maintain the parsing stack as a data structure threaded through the functions instead of using recursive calls - this means we can always interrupt, return from the functions, yield and later use that state to resume the parsing from where it was left.

michalmuskala avatar Dec 25 '17 20:12 michalmuskala

@michalmuskala

Yes, but we can't use serde directly - the problem is that it is not pre-emptive

This is a bit unexpected especially as Rust is meant to be highly concurrent and I can't find a proof that serde is not thread safe.

RumataEstor avatar Dec 29 '17 02:12 RumataEstor

@RumataEstor It's not about thread safety. Rust and Elixir does concurrency in different ways, Rust uses OS threads and Elixir uses lightweight processes. When serde runs it will block a scheduler until it is done running so when decoding or encoding large JSON objects you can disrupt the scheduler.

ericmj avatar Dec 29 '17 09:12 ericmj

I don’t mean it’s not thread safe - it is. Preemptive means we need to be able to pause the execution of the parser/generator at arbitrary moments to yield the scheduler thread to other elixir/erlang processes.

michalmuskala avatar Dec 29 '17 09:12 michalmuskala

After 5 years, I finally got around to this. Check out https://github.com/spawnfest/json_native!

michalmuskala avatar Oct 16 '22 20:10 michalmuskala