前一段时间Rails on Ruby创始人David Heinemeier Hansson(DHH)在Twitter上发了一篇推文,如下图,文中比对了苹果A12、其他手机CPU和Intel CPU对Java处理速度的比对。可以看到苹果A12在Java上的表现明显超过其他手机CPU,甚至超过了Intel的PC级CPU!DHH因此发问:为什么苹果A12在JS处理速度上这么快?
大神DHH竟然也有知识盲点啊!
ARMv8架构的演进
我们知道现在的手机CPU基本上是基于ARMv8架构,ARMv8架构是不停演进的,从最早的ARMv8.0,ARMv8.1,ARMv8.2,到目前市面上可以看到的最新的芯片版本ARMv8.3(当然现在还有ARMv8.4等在开发中甚至ARMv9,只是暂时未见有芯片产品出炉)。
目前高通,MTK和华为海思的手机CPU最高到ARMv8.2版本,具体如下图。而苹果A12则到了ARMv8.3!市面上最早的一款ARMv8.3产品,而且是迄今为止唯一的一款ARMv8.3产品。
ARMv8基本架构
上面介绍了基本的ARMv8背景,现在开始进入正题。回到DHH的问题,原因是ARMv8.3相对于之前的版本,多出了一条相对于Java的指令FJCVTZS (AArch64) or VJCVT (AArch32),在这有必要再多啰嗦一句关于AArch64和AArch32. 他们是ARMv8有两种执行状态(Execution states),AArch64支持A64指令集(instruction set),而AArch32可以支持A32和T32指令集。苹果A12芯片支持A12指令集,因此我们以AArch64的FJCVTZS为例。
ARMv8.3 新增Java指令
Java对于数据的处理都是基于双精度浮点数据来进行,JS在进行bit-wise操作的时候,普通CPU需要把这个双精度浮点数据转换成32bit整形数据,同时检查这个转换后的数据是否真的是整形数据;这种场景在JS中还是相对比较常见的场景。
这就是那个Java的奇葩规定:
ARMv8.3 spec中关于FJCVTZS指令的说明:
一般CPU是怎样处理上面的场景呢?利用Java中规定的ToInt32()函数,每个浏览器(FireFox、Chrome、IE和Safari)都会实现自己的ToInt32()函数来完成转换功能。对此感兴趣的小伙伴,可以下载下FireFox的源代码下来看看。
显而易见,ToInt32()这个函数需要多条指令才能完成,运行速度是比较慢的,而FJCVTZS指令则可以一条指令就可以搞定,将大大加速了JS处理性能。
回头说说其他加的CPU,高通、华为海思、联发科等一众都是采用的ARM公司的CPU,都还在ARMv8.2阶段,还没引入FJCVTZS 指令,三星虽然是自研的CPU但也还没有引入FJCVTZS指令,Intel还没有专门针对JS的指令,这样一对比,Apple A12 JS牛X性能就凸显出来了。
题外话
ARMv8.3在引入了JS浮点转换指令后,下面是国外一小伙的吐槽。相信代表了好多小伙伴的声音。
参考文献:
https://en.wikipedia.org/wiki/Apple_A12
https://www.slideshare.net/chiounan/tphcc2-ianrickards-64bitandroidopenslidesrickards
https://www.w3schools.com/js/js_numbers.asp
https://reviews.llvm.org/D36785
https://patches.linaro.org/patch/81061/
https://community.arm.com/processors/b/blog/posts/armv8-a-architecture-2016-additions
https://software.intel.com/en-us/articles/intel-sdm
https://jibbering.com/faq/notes/type-conversion/
文章来源:未知