[翻译] 你懂 JIT compiler 了吗?

楼主: PsMonkey (痞子军团团长)   2013-03-20 17:26:49
原文网址:http://plumbr.eu/blog/do-you-get-just-in-time-compilation
译文网址:http://blog.dontcareabout.us/2013/03/jit-compiler.html
BBS 版用 markdown 撰写
另外,这篇翻的真的很不顺,可能很多都有问题
不过我也怀疑当初写的人就写的很卡...... [逃]
______________________________________________________________________
还记得最后一次被写 C 的人笑是什么时候的事情吗?
Java 真的有够慢、慢到他们打死也不会考虑用这样的语言?
其实从很多方面来看,这种讲法还是成立啦。
但是在大型企业的软件骨干中(这是 Java 的典型用途),
Java 的效能绝对可以跟其他技术相抗衡。
这可能都要感谢神奇的 JIT。
在解说 JIT compile 技巧前,让我们先多讲一些它的背景。
你可能还记得,Java 是一种 interpreted language。
大多数人都知道 Java compiler(`javac`)跟 C 的 compiler 不一样,
并不是直接将 Java 的原始码 compile 成处理器的指令。
相反地,它产生的是统一[规格]、与机器 binary 格式无关的 bytecode。
在执行期,JVM 会 interpret bytecode,
这是为什么 Java 在跨平台上会这么成功的主要原因,
你可以在某个平台上写完、build 一份,然后在其他的平台上头执行。
[规格]: http://docs.oracle.com/javase/specs/
另一方面,这也产生了一些不良影响。
其中最严重的是 interpret 通常比直接 compile 成
平台限定的原生 binary 码来得慢。
[Sun] 在 90 年代后期就已经了解这个严重度,
当时他们请了 Cliff Click 博士来提供解决方案。
[Sun]: http://en.wikipedia.org/wiki/Sun_Microsystems
让我们欢迎 [HotSpot] 出场~~
这个名字源自于 JVM 辨别你程式当中“hot spot”的能力,
hot spot 表示 bytecode 当中经常使用到的片段。
接着它们将目标对准大范围的最佳化、以及将程式码 compile 成特定处理器的指令。
这些最佳化以最少的 overhead 让影响效能的关键 code 有很好的效能。
在某些情况下,调整好的最佳化 [JVM] 效能可能超过手工的 C++ 或 C。
[HotSpot]: http://www.oracle.com/technetwork/java/javase/tech/
index-jsp-136373.html
[JVM]: http://en.wikipedia.org/wiki/Java_virtual_machine
[JVM] 当中负责这些最佳化的部份称之为 [Just in Time][JIT](JIT)compiler。
它利用了一个有趣的程式特性:
大多数时间都花在少数的程式码上,几乎所有程式都是这样。
有别于将你的程式码整个 compile,
JIT(Java [HotSpot] VM)用 interpreter 立即执行程式、
然后在执行时分析你的程式码,找出那些 hot spot。
Then it focuses the attention of a global native-code optimizer
on the hot spots.
透过避免 compile 极少执行的程式码,
Java [HotSpot] compiler 可以把正更多注意力放在程式中影响效能的关键部份。
这代表你的 compile 时间整体来说不会增加。
在程式执行中会持续动态监测 hot spot,
所以它会根据你的 application 使用方式来即时调整效能。
[JIT]: http://en.wikipedia.org/wiki/Just-in-time_compilation
[JIT] 用了很多技术来达到效能优势,像是去除没用的 code、
跳过边界值检查、移除多余的加载、inline method...... 等等>
下面这个例子展示了 [JIT] 如何使用这些技术来达到更好的效能。
第一段程式码是开发人员写的,第二段程式码是 HotSpot 认定这段很“hot”,
然后用上了最佳化的魔法:
1. 还没作最佳化的程式码:
class Calculator {
Wrapper wrapper;
public void calculate() {
y = wrapper.get();
z = wrapper.get();
sum = y + z;
}
}
class Wrapper {
final int value;
final int get() {
return value;
}
}
1. 最佳化过后的程式码:
class Calculator {
Wrapper wrapper;
public void calculate() {
y = wrapper.value;
sum = y + y;
}
}
class Wrapper {
final int value;
final int get() {
return value;
}
}
第一个 class 是开发人员写的例子,第二个是 JIT 处理过后的样本。
这里头包含了几种最佳化的技术。让我们来看一下最终结果是怎么做到的:
1. 还没最佳化的程式码。在还没被判定成 hot spot 时,程式码会这样执行:
class Calculator {
Wrapper wrapper;
public void calculate() {
y = wrapper.get();
z = wrapper.get();
sum = y + z;
}
}
1. inline method:用 `b.value` 取代 `wrapper.get()`,
不透过函数呼叫而直接存取 `wrapper.value` 来减少延迟。
class Calculator {
Wrapper wrapper;
public void calculate() {
y = wrapper.value;
z = wrapper.value;
sum = y + z;
}
}
1. 移除多余的加载:用 `z = y` 取代 `z = wrapper.value`,
所以只存取区域变量而不是 `wrapper.value` 来减少延迟。
class Calculator {
Wrapper wrapper;
public void calculate() {
y = wrapper.value;
z = y;
sum = y + z;
}
}
1. copy propagation:用 `y = y` 取代 `z = y`,
没有必要再用一个变量 `z`,因为 `z` 跟 `y` 会是相等的。
class Calculator {
Wrapper wrapper;
public void calculate() {
y = wrapper.value;
y = y;
sum = y + y;
}
}
1. 消除不用的程式码:`y = y` 是不必要的,可以消灭掉。
class Calculator {
Wrapper wrapper;
public void calculate() {
y = wrapper.value;
sum = y + y;
}
}
这个小例子包含了几个 [JIT] 用来提升效能的强大技术。
希望它可以有助于了解这些威力强大的概念。
喜欢这篇文章吗?我们肚子里头还有一堆咧。
请订阅我们的 [RSS] 或 [Twitter] 吧!
[RSS]: http://plumbr.eu/blog/feed
[Twitter]: https://twitter.com/JavaPlumbr
下面是这篇文章用到的参考资料(不包含那两个愤怒的 C 开发人员):
* http://www.oracle.com/technetwork/java/whitepaper-135217.html
* http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html
* http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/
geninfo/diagnos/underst_jit.html
楼主: PsMonkey (痞子军团团长)   2013-03-20 22:06:00
觉得标题的 get 应该是“懂”比较对,像 I got you

Links booklink

Contact Us: admin [ a t ] ucptt.com