Oh yes, quite a bit of profiling, certainly. I've used tools like valgrind and cachegrind, perf, manual instrumentation, JMX, or even just `time`, as well as a dozen others I'm sure.
> But the one thing I’ve learned is I’m always very surprised by where the hotspots in my code come from.
Are you looking at small or large codebases? The code in the article is quite tiny. The major complexity in terms of understanding that code's performance is really just V8 specific stuff. As someone who only reads casually about V8 I'd be much less comfortable guessing about performance.
To be clear, there's plenty of times where I can't guess. Certain languages make it really hard, like if there's a lot of inheritance I can't "glance" at the code at all, I have to dig all around the hierarchies. Extremely annoying, I'll 100% have to benchmark in that sort of language.
> Compilers are crazy these days, and it’s very difficult to tell if something will be slow or if the compiler is going to clean it up behind the scenes and make it a non issue.
For sure, like I said, the big question here is V8. If this were in a system I'm more familiar with I'd have an easier time telling you which optimizations would or would not work. But even still it's not too hard to guess, sometimes. Knowledge of your runtime is the big thing, I think. For example, reusing an allocation might seem like a trivial optimization but allocations can actually have effects (like failing) so an optimization that removes one would be somewhat aggressive - the situations where that optimization will kick in is going to depend on your compiler/JIT.
As an example, it's really easy to find documentation about how escape analysis in the JVM works. There are a few rules and you can sometimes look at code and evaluate those rules in your head. You could use those similar rules for C# or Go or JS but you'd be risking that the rules are different in those languages.
Example of an article that goes into some depth on JVM escape analysis and the implications: https://blogs.oracle.com/javamagazine/post/escape-analysis-i...
> Because of this, I’ve just learned to never trust my intuition when it comes to this.
That's totally fine fwiw. I'm definitely pro "just benchmark it", but I will maintain that:
a) Benchmarking and profiling are hard. Getting a representative benchmark of your system under load is particularly difficult and a GC can have wildly different performance characteristics under load.
b) It's often not that hard to guess. The more complex the runtime, the more complex the system, the harder it is to guess.
> and I don’t even know how you would begin to intuit where a hotspot would be.
The short answer is you just learn about how a JIT works just like you learn about how a compiler works.
Just to reiterate, I'm very much pro "measure before optimizing". Like, very pro. But also, the article shows that guessing definitely works. And I think guessing is super effective and a fine tool to use at times. Perhaps I've overstated my ability to "just look at code and see the slow bits" - it's obviously very much dependent on the code itself, my familiarity with the underlying components such as the runtime or compiler, and perhaps a bit of luck.