Node: synchronous code runs faster than asynchronous code

Writing Node code? What for?

If you’re coding your own web server, you’ve probably read that you should never use fs.readFileSync(): instead, you should use fs.readFile() and endure callback spaghetti.

I’ll add a corollary: if you aren’t coding your own web server, use fs.readFileSync().

Prefer synchronous code, when it’s an option. It’s faster and simpler. For instance, reading lots of small files:

In this example, synchronous code is 6–7 times faster than asychronous code.

Async pundits may protest. “Why not read the files in parallel?”, they’ll ask. (The answer: that causes EMFILE: too many open files — and it takes longer to generate that error message than it takes synchronous code to read all the files. A workaround would take lots more code, and it would still be slow.) Perhaps they’ll say, “But that isn’t real-world code!” … to which I’ll reply: I’ve observed dramatic real-world speedups and simplifications by switching to synchronous code.

When to use synchronous code

The basic question is: “should code run in the background while I’m reading this file?” If yes, use async. Otherwise, use sync.

It’s often a judgement call. Here are the basics:

Use sync for in-memory operations — async is a complete waste when you aren’t making blocking calls.

Use async when designing a library that makes blocking calls — unless you know all users want to use your library synchronously. You can add synchronous code as a feature once you’ve finished the async version.

Use async when a library you depend on forces async — because you have no choice. But consider contributing a synchronous version of the library.

Use sync for non-parallel tasks — such as computations or system-administration scripts.

In sum: async is often a mistake. Code appropriately.

Next up: streams.

Journalist, ex software engineer

Journalist, ex software engineer