ITPUB

写错变量名,Java 性能居然快了 37%?

把 userName  替换成 usrNme,性能直接飙升 47ms?

兄弟们,我学了十几年 Java,今天算是开了眼了。

这是我在 Medium 上看到的一篇神文。

Image

作者信誓旦旦地说:拼写错误的变量名能让 Java 性能起飞。

没错,就是这么离谱。

他说自己凌晨两点重构 SpringBoot 服务时,猫跳上了键盘??

Image

导致他部署的代码,从这样变成了这样。

Image

结果第二天看监控,API 延迟从 127ms 降到了 80ms,足足提升了 37%。

Image

回滚代码后,延迟又回去了。

他说他跑了2847 次 benchmark  ,得到了这个结果:

Image

先纠正一下,这哥们说的其实是字段名,不是变量名。他这都没搞清楚。

我一开始以为他在整活,直到看到他的“解释”:

Image

简单总结下就是:

  • 字符串越长,hashCode() 算得越慢
  • 名字越相似,越容易 hash 冲突
  • 反射大量使用 String.hashCode(),所以会慢

结论是:字段名越烂(越短、越随机),Java 跑得越快

听起来好像有点道理?但仔细一想,全是漏洞。

首先,字符串长几个字符,hashCode 计算也就多几个循环,在现代 CPU 面前就是纳秒级的事。

你 API 延迟动不动差几十毫秒,真以为是字段名搞的?

其次,他说“长且相似的字段名容易冲突”。

你来,我们看看 String.hashCode() 的源码

publicinthashCode(){
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;

for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
return h;
}

就这简单的算法,他是怎么得出“长且相似就冲突更多”的结论的?

再说反射。

反射找字段的核心是 遍历 + equals() 比较名字,根本不是靠 hash。

退一万步,就算用 hash,又怎么了哥哥?

hashCode 是有缓存的!

publicinthashCode(){
int h = hash;
if (h == 0 && value.length > 0) {
        ...
        hash = h;
    }
return h;
}

再退十万步,就算没有缓存,少几个字母,少乘几次 31 ,就能省出几十毫秒?

那你把代码变量全改成“a、b、c”不是直接起飞了?

真正拖慢服务的是什么?

网络、数据库、锁、GC、I/O、线程调度……

这些随便抖一下就是几十毫秒。

字段名那点影响?蚊子腿都嫌它细。

最讽刺的是:这篇文章不是在反串,他是真信。

更讽刺的是:国内搬运过去以后,一堆人点赞,说“学到了”。

Image

我也受教了。

原来系统慢,不是数据库、不是 GC、不是锁竞争。

是因为你的代码,缺一只会跳键盘的猫。

Image