Flamegraphs are wonderful. Me: looks at my code. "sure, ok, looks alright." Me: looks at the resulting flamegraph. "what the hell is this?!?!?" I've found all kinds of crazy stuff in codebases this way. Static initializers that aren't static, one-line logger calls that trigger expensive serialization, heavy string-parsing calls that don't memoize patterns, etc. Unfortunately some of those are my fault.
I've never used flamegraphs but would like to know about them. Can you explain more? Or where should I start?
A 40-line fix eliminated a 400x performance gap
61–70 of 81 posts
Re: A 40-line fix eliminated a 400x performance gap
#62Flamegraphs are wonderful. Me: looks at my code. "sure, ok, looks alright." Me: looks at the resulting flamegraph. "what the hell is this?!?!?" I've found all kinds of crazy stuff in codebases this way. Static initializers that aren't static, one-line logger calls that trigger expensive serialization, heavy string-parsing calls that don't memoize patterns, etc. Unfortunately some of those are my fault.
Re: A 40-line fix eliminated a 400x performance gap
#63Earlier quoted context omitted.
This seems like more of a philosophical argument than a practical one.
No, it is a very practical one and I'm actually surprised that you don't see it that way. Benchmarking is hard, and if you don't understand the basics then you can easily measure nonsense.
The mean does get proper statistical treatment (t-distribution confidence interval), but you're right that JMH doesn't compute confidence intervals for percentiles. Reporting p0.00 with three significant figures is ... optimistic.
That said I think the core finding survives this critique. The improvement shows up consistently across ~11 million samples at every percentile from p0.50 through p0.999.
Re: A 40-line fix eliminated a 400x performance gap
#64While I don't particularly like the IO overhead and churn consequences of real files for performance metrics, I get the 9p-like appeal of treating the virtual fs as a DBMS/API/ABI.
Re: A 40-line fix eliminated a 400x performance gap
#65It took seven years to address this concern following the initial bug report (2018). That seems like a lot, considering how instrumenting CPU time can be in the hot path for profiled code.
400x slower than 70ns is still only 28us. How often is the JVM calling this function?
Re: A 40-line fix eliminated a 400x performance gap
#66Re: A 40-line fix eliminated a 400x performance gap
#67You can do even faster, about 8ns (almost an additional 10x improvement) by using software perf events: PERF_COUNT_SW_TASK_CLOCK is thread CPU time, it can be read through a shared page (so no syscall, see perf_event_mmap_page), and then you add the delta since the last context switch with a single rdtsc call within a seqlock. This is not well documented unfortunately, and I'm not aware of open-source implementations…
Re: A 40-line fix eliminated a 400x performance gap
#68You can do even faster, about 8ns (almost an additional 10x improvement) by using software perf events: PERF_COUNT_SW_TASK_CLOCK is thread CPU time, it can be read through a shared page (so no syscall, see perf_event_mmap_page), and then you add the delta since the last context switch with a single rdtsc call within a seqlock. This is not well documented unfortunately, and I'm not aware of open-source implementations…
clock_gettime is not doing a syscall, it's using vdso.
Re: A 40-line fix eliminated a 400x performance gap
#69Earlier quoted context omitted.
No, it is a very practical one and I'm actually surprised that you don't see it that way. Benchmarking is hard, and if you don't understand the basics then you can easily measure nonsense.
You raise a fair point about the percentiles. Those are reported as point estimates without confidence intervals and the implied precision overstates what system clock can deliver. The mean does get proper statistical treatment (t-distribution confidence interval), but you're right that JMH doesn't compute confidence intervals for percentiles. Reporting p0.00 with three significant figures is ... optimistic. That sai…
Re: A 40-line fix eliminated a 400x performance gap
#70Earlier quoted context omitted.
400x slower than 70ns is still only 28us. How often is the JVM calling this function?
It depends. If you’re doing continuous profiling, it’d make a call to get the current time at every method entry and exit, each of which could then add a context switch. In an absolute sense it appears to be small, but it could really add up. This is what flame graphs are super helpful for, to see whether it’s really a problem or not. Also, remember that every extra moment running instructions is a lost opportunity t…