r/node•
indeyets

Async JSON parser/serialiser

Is there some maintained asynchronous JSON parser/serialiser for nodejs?

I don't need it to be fast. I need it to yield often to let other tasks run in parallel.
I don't need it to support browsers. NodeJS is enough for my case.
Once upon a time, there was BFJ https://gitlab.com/philbooth/bfj which fits the bill perfectly, but, unfortunately, is not maintained anymore. It's still usable, I guess. But 3 years is a lot of time.

Posted Sep 1, 2023, 5:15 PM UTC

136
the9engines•

you can build one using worker threads

1
indeyetsOP•

I can't. that would be… many-many thousands of threads. no point to use nodejs at that point. I want my greenlets :)

1
faljse•

-v please

Why would that result in thousands of threads.. and whats the issue with nodejs here?

1
indeyetsOP•

Worker threads are represented as real OS-level threads, as far as I remember and those have overhead. NodeJS app occupies single thread by default (there are some helper-threads used by NodeJS internally, but that is irrelevant here) which means that OS has less things to do and asynchronous queues for I/O are really light-weight. That’s exactly what makes NodeJS (and other asynchronous frameworks great) — they saturate cpu cores with less overhead

1
faljse•

single threaded code can only ever saturate 1 cpu core.

The most efficient way to parse many json file is to create one thread per cpu core an queue them accordingly

1
the9engines•

if you decide to try, the very first example on the docs page is how to do almost exactly what you want https://nodejs.org/api/worker\_threads.html

1
PatrickBauer89•

Why many thousands? One worker can parse many json files (one after another) without affecting the main thread. What are your actual requirements?

1
kurtextrem•
1
indeyetsOP•

Thank you. But it’s unmaintained for 3 years too 😨

1

"unmaintained" doesn't mean "unusable". There may be nothing left to update in some packages because they are feature-complete, don't have any bugs reported, don't have dependencies that need updating, etc. Just because it isn't "new, shiny" doesn't mean you can't use it.

1

This. The mechanics of json parsing haven't changed in the last 5 years.

1
nj47•

There are literally comments in the issues tracker from the maintainer in the last 2 weeks. Last updated and not maintained are very very different things.

1
SilverLion•

Could you just fork it and run a security check on the dependencies? There's not too many...

1
indeyetsOP•

Yeah. That’s the backup plan

1
boneskull•

Fork it, update the deps and re-publish under a scope. Someone may find it helpful.

1
bwainfweeze•

Yielding (in the cooperative threading rather than generator sense) in node is a bit tricky, and got more tricky around Node 14, where I had to fix some unit tests because we discovered replacing an async method with a sync mock results in a noop for await, and so our expects and calls were in the wrong order.

A SAX style parser like fast-json will get you incremental parsing but unless you throw some async code in on purpose the attempts to yield may get optimized away.

You’ll need to wrap setImmediate or setTimeout(…,0) in a Promise to really force multitasking. Whether you write it or find a module that does is a separate question.

1
tswaters•

One thing you might consider is ajv.

You give it a JSON Schema and it'll give you functions for serializing and parsing that are quite a bit faster than JSON.{stringify,parse}

Fastify uses ajv for parsing/serializing requests and responses and that is one of the reasons it has impressive benchmarks when compared to express.

I'm not entirely sure if the actual serializing/parsing it does is properly async or not, but if it takes considerably less time than other methods, the yielding may not be necessary.

1
tswaters•

Also worth noting that a module doesn't necessarily need to get updated regularly for it to be considered useful. It's nice being maintained to keep dependencies up to date, avoid potential warnings if they have `engines` defined with defined nodejs versions.... but if it worked before it's highly likely it'll keep working. Worse comes to worse you can fork it to keep deps up-to-date.

1
theQuandary•

There used to be a simdjson wrapper around, but I think it's not maintained. I'd fork that. You get stuck maintaining the wrapper library, but get a massively fast C++ library that you don't have to maintain.

1
guest271314•

What is the use case? What are you doing now?

1
indeyetsOP•

I’m processing a lot of json traffic. Mostly websocket, but sometimes REST too. Built ins work, but they are synchronous, thus they block execution and result in different execution profile: one thread can process only one json file at once. Once you have 10k parallel requests per thread this becomes noticeable. I want to process json requests in parallel. This means that each of them will be processed slower, but there would not be waiting time (no queue). This would allow me to have a finer grained control of execution speed as adding new cpu core would result in predictable linear doubling of speed.

That’s not something one should care about initially. It’s needed only under high load

1
guest271314•

What are you doing now to process 10k parallel requests in a Node.js environment?

1
indeyetsOP•

Node easily handles 10k. Just like any async framework. One doesn’t need anything special to do this. Avoid synchronous actions and it will work. JSON processing is a rare case of synchronous only facility in node

1
guest271314•

Processing JSON is no different from processing any other data.

I stream real-time audio as JSON at 44100 samples per second without any gaps or glitches in playback observable in the client.

1