
Node.js: Some quick optimization advice - SanderMak
https://medium.com/@c2c/nodejs-a-quick-optimization-advice-7353b820c92e
======
mixonic
This is a good thing to raise awareness of, but the solution is poor advice.

Asking developers to remember the "gotcha" of 600 characters is not really
viable. Instead, if this is important to you, consider the addition of
minification or comment stripping to your production deployment process.
Minification will also make the variable names and syntax use shorter, saving
you further precious characters.

Learn the problem, but automate the solution.

~~~
nevi-me
In the context of the article being on nodejs code; I don't know about other
developers, but I don't minify my production nodejs code because it runs
directly on the server. Whether I have `var nameThatIsStupidlyLong` or `var
nTISL` doesn't make a difference because size of code isn't a concern.

What do other developers out there do?

~~~
smt88
Yeah, but the whole point of the article is that the names of your variables
(and even your comments!!) _do_ make a difference in performance.

~~~
nacs
In this one context, this one micro-optimization applies but for 99% of other
cases, they don't (and shouldn't).

Note the 'benchmark' in OP is run 500 _million_ times to see the performance
difference. This is definitely not a common scenario.

~~~
smt88
For me, it's more the principle of the thing. This just seems like an insane
way for an interpreter to behave. Even more insane is the proposal of
minifying server-side JS!

~~~
sim0n
Not that insane considering many people are using things like Babel to run
ES6/7 code. If you're already compiling that code to ES5 for production,
there's no harm in also minifying things.

------
dap
This is a microbenchmark. It's a tight loop that calls the function 500
million times. The function itself just adds two numbers. It's pretty close to
the best possible improvement for inlining a function. If that's what your
program does, and it's a big part of what your program does, then inlining it
may be a big performance win. Even then, addressing this may not be a
worthwhile tradeoff. Even then, as others have pointed out, you could use a
minimizer.

If your program is not CPU-bound, or if it doesn't have a function that's
called millions of times in a tight loop, or if that doesn't make up the
majority of time spent on CPU, or if that function does more than execute a
couple of instructions, then the performance difference will likely be
enormously less.

~~~
fla
I think the oddity here is that the function length takes the comments into
account.

~~~
dap
Agreed that's interesting (in a mostly academic sense), but the thrust of the
post is about using that fact to make choices in writing code, and there's an
awful lot of discussion here about that idea. That's what I was addressing.

------
pauljz
If you're wondering why comments are a factor at all, and aren't just
discarded by the lexer, remember that comments in JS are preserved and
available to things like `Function.prototype.toString()`. I've seen this used
to do evil multiline string support a few times. Slap the multiline string or
template into a comment inside a function and then have another function that
toStrings it and strips the boilerplate.

This sounds like a horrifying hack but it's also pretty similar to how
Angular's shorthand DI works.

~~~
clessg
> I've seen this used to do evil multiline string support a few times.

Love me some FOAM: [https://github.com/foam-
framework/foam/blob/master/apps/todo...](https://github.com/foam-
framework/foam/blob/master/apps/todo/js/com/todomvc/Todo.js).

~~~
Dru89
That might be one of the scariest things I've looked at all day.

~~~
clessg
It only gets better. [https://github.com/foam-
framework/foam/blob/master/apps/todo...](https://github.com/foam-
framework/foam/blob/master/apps/todo/js/com/todomvc/Controller.js)

~~~
phpnode
it's incredible that that project has 11,000 commits, a huge amount of effort
has gone into it but the code is _really_ unpleasant to read. I feel like I
must be missing something about FOAM - who is using it and why?

~~~
strayptr
Let's stop trashing on people's work.

The success of an endeavor is proportional to the number of shitty hacks that
have come before it. Sometimes this it true in a literal sense -- sometimes a
project consists of shitty hacks. But the astute reader will notice that a
hack is only known to be shitty because _someone did it_ , and had the courage
to make their example public.

Do we reward their courage? No. We act like cliquish teenagers and rip them
apart.

I don't mean to single you out. But this subthread consists of a developer at
Amazon, an unknown, and a founder -- the very types of people I wanted to
respect -- yet the content is little more than "Look at how stupid these
people are." What kind of example are we setting here?

Be excited about X! Whether X is FOAM, Javascript, COBOL, C++, Python, Erlang,
Scheme, NPM, ASDF, Vim, Stallman, or a song. Be happy. Be amused. Be anything
but bitter.

In this instance, FOAM shows what's possible. Is it necessarily a good idea?
Who cares! We've learned something new! Be excited!

How certain are you that an idea that strikes you as bad is actually bad? For
every possible circumstance? What about with a slight tweak? In fact, "An idea
that seems bad" is the short definition of "startup."

Most ideas that seem bad are, in fact, bad. But it's important to fully
explore the problem space before dismissing them, else you'll dismiss
Facebook.

This subthread is about a software technique, not a startup idea. But is it
really such a different domain? Would the idea of Python have survived if it
had been introduced in the era of Multics? It wasn't a compiled language, so
it couldn't hope to survive back then. Yet its time was coming, whether or not
it would have been dismissed at the time.

"Under what circumstances could this be a good idea?" That's the valuable
question. And if you also have a good answer to "Why now?" then you may be
onto something. In fact, you might be one of the first people to notice that
an idea has flipped from bad to good. Seems like a pretty powerful position.

It seems like most influential work started as a hack. (TeX is a notable
exception.) So if you want to do influential work, be delighted by hacks.
It'll make them easier to explore, and you might end up in a position few
others realize is valuable.

~~~
escape_goat
Most everyone agrees with you in general about the usefulness of "trashing
other people's work", but I think your response here is disproportionate to
the circumstance.

------
constexpr
The bug has been marked as WontFix by the V8 team:
[https://code.google.com/p/v8/issues/detail?id=3354](https://code.google.com/p/v8/issues/detail?id=3354).
It looks like they are considering fixing it for TurboFan and not for
Crankshaft, but I'm not sure what that means. Does that only apply to asm.js
code?

~~~
bananaoomarang
I think Turbofan aims to supersede Crankshaft, but gradually.

~~~
oso2k
Turbofan is an additional layer of optimization after Crankshaft.

------
spullara
Wow, the v8 optimizer can sometimes be a pretty blunt instrument. Shouldn't it
look at the size of the inlined function after it compiles it to some
intermediate state that erases things like comments and names?

~~~
striking
Such a state does not exist inside V8. Things happen as they are parsed. Since
V8 has no idea what a piece of JS will do until it gets all the context, it
has to use a silly thing like character count to perform inlining. It could
create an intermediate state, but that would require a code overhaul that
would likely slow down the entire thing anyway.

If I had to suggest a change, I would use the 600-char count as a starting
point for one-time functions, and then count the number of calls to a
function, counting how many instructions it produces (basically tossing an
incrementing variable into the compilation state, and storing it per Function
object).

But then again, I've never played with the inside of V8, only the outside. I
consider myself lucky to be in that position, because V8 is pretty dang sweet.

~~~
alkonaut
> Things happen as they are parsed.

If comments aren't completely ignored by the parser, then there has to be some
case where a comment inside a function has an observable effect?

~~~
ycitm
Yup, see @pauljz's comment above -
[https://news.ycombinator.com/item?id=10375297](https://news.ycombinator.com/item?id=10375297)

~~~
alkonaut
I still don't understand that. Function.prototype.toString() wouldn't break
because the parser stripped the comments, it would just output the source
without comments? Does any code anywhere depend on the comments being
preserved?

~~~
spullara
People literally toString functions and parse them to implement features.
Those features depend on there being comment text in the function that they
parse. Pretty much a terrible hack but it is true that you can't remove the
comments without breaking current code.

~~~
alkonaut
Wow. That's just something that should be an obvious fix in a future ES. Not
only does it hurt the optimizer, it also seems to imply that the content of
comments sometimes has semantic meaning in the code, such as people having
invented directives etc.

Surely this must be undocumented features of the language spec?

------
mhd
One comment mentions a quite significant speedup when switching the variable
initialization step of the for loop from let to var. As excepted, you'll also
get this if you keep the "let" keyword, but move it outside of the loop.

What kind of optimization step is prevented here?

------
tambourine_man
Posted that yesterday, didn't get much traction.

Whenever I begin to convince myself that JS and Node are actually fine
languages / environments to code on, some weird edge case like this pops up.

Not entirely sure if it's just its popularity, which is bound to expose its
rough corners, or if it's fundamentally bad designed (written in 10 days in
the late 90's, etc)

~~~
diggan
Well, to be fair. Node is not a language and this hack is not a "feature" or
whatever of the language, rather it's a hack to get V8 to inline functions.
JavaScript as an language is all right, but as always, making this language
work and perform in multiple environments is tricky sometimes.

~~~
draperp
Sure. And CPython isn't a language. It's the canonical Python implementation
that is used 99% of the time.

When it comes to non-browser production code (e.g. servers), it's NodeJS or
nothing.

------
bshimmin
This cheerfully reminded me of the thing in MRI Ruby of (relatively recent)
yesteryear where strings longer than 23 characters were twice as slow, qv.
[http://patshaughnessy.net/2012/1/4/never-create-ruby-
strings...](http://patshaughnessy.net/2012/1/4/never-create-ruby-strings-
longer-than-23-characters)

------
vivram
Good to know as a "gotcha" but typically when you get to an optimization like
this you should have covered all other bigger optimizations like minification,
... that this won't actually return big yields.

------
vvoyer
Who need this? Prople writing really really performant code like parsers. Who
write parsers? 1% of ppl? Sad this get so much exposure. Stop losing time with
micro optimization, this is a bug that's it.

------
746F7475
I'm at work and can not test this out, but does adding whitespaces increase
the function length here?

------
amelius
Isn't there a way to force the inline optimization of a function, regardless
of the character count?

------
m1sta_
I had this exact thing happen to me. It drove me crazy. Thank you!

------
WorldWideWayne
So, is this is a point in favor of _not_ commenting your Javascript code or
using inline docs?

Historically, I preferred to use inline JsDoc style comments as the source of
documentation for my public APIs. Recently though, I decided that I didn't
like them and that I wanted something better. I was hoping to find some tool
that parses my JS to AST, figures out what was being exported (e.g. what was
public) and writes a JSON document that I could diff over time, to figure out
what was documented and what wasn't (in my external docs). So far, I have
found this project called `doctor` which sounded close to what I'm looking
for, but it still relies on comments ~
[https://github.com/jdeal/doctor](https://github.com/jdeal/doctor) ~ So, I
might have to write it myself using something like Esprima to get the AST...

~~~
untog
As others have said, you can always strip comments in production builds. But I
agree that this is utterly silly - I'd like to see a movement to deprecate
including comments in parsing at all. Anything that makes use of such a
feature is hacky weirdness from the start.

~~~
STRML
Function.prototype.toString() should be deprecated anyway. There are very few
to no legitimate uses of it that are any better than awful eval() hacks.

Re: this comment, if you just don't make huge comments _inside_ the body, but
rather above it - as is the usual standard - this is less of an issue.

~~~
draperp
Every JS dependency injection framework that I've ever seen uses it.

~~~
untog
Serious question: why use a dependency injection framework with JS?

------
bru_
At first I thought the comment was actually serious and couldn't believe it
before I read the whole article. Thanks for pointing this out

