java性能优化--编译器优化

353 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

前一篇讲到java是即使编译器JIT,本章我们来具体学习一下java有哪几种编译器类型,如何根据业务场景选择最合适的编译器。

编译器类型

通常有两种编译器,我们针对编译器的调优,主要是如何选择合适的编译器。

这两汇总编译器分别是serverclient。我们在选择编译器时使用的参数分别是-serverclient

在有些地方,这两种编译器会被称作:

  • C1编译器 - client
  • C2编译器 - server

不同点

上面提到的两种编译器,主要不同在于编译时机不同。

client编译器开启编译的时机相比server编译器要早,代码开始执行阶段,client编译器相对要更快,编译早意味着可以编译更多的代码。

而server编译器通常在运行过程中,当有代码变热时,对热点代码编译,在等待编译的时候可以做很多事情,可以对编译代码进行更好的优化,是的编译后的代码,相比client编译器有更快的运行速度。

真的需要人来选择编译器吗?

相信会有人提出这种疑问,让jvm自己选择使用何种编译器不是更好吗?开始时使用client,运行中使用server?

这种技术被称为分层编译技术。在java7的版本中引入分层编译,同时不断地进行优化。分层编译的引入使应用能更好的发挥性能。在JAVA7当中,由于存在一些问题,默认是关闭的,而在JAVA8当中,分层编译是默认开启的,我们可以使用如下的命令查看:

[root@hecs-402944 opt]# jps
1434 jar
1567 Jps
655 WrapperSimpleApp
[root@hecs-402944 opt]# jinfo -flag TieredCompilation 1434
-XX:+TieredCompilation

+表示开启,我使用的java8,默认开启。

编译器的权衡

通过前面的描述,我们知道编译器分为三种:

  • client
  • server
  • -XX:+TieredCompilation

那么三种编译器的效率是怎样的?外面不展示演示过程,直接给结论。分为不同的场景:

启动时间

如果以快速启动时间为目标:

  • 少量代码,三种编译器效率相同
  • 代码较多,client < -XX:+TieredCompilation < server
  • 大量较多,client < -XX:+TieredCompilation < server

在绝大多数场景,优化启动时间可能都不是主要的任务,所以这里推荐使用:server或者-XX:+TieredCompilation.

批量处理

如果以批量处理效率为目标:

  • 少量数据,client < -XX:+TieredCompilation < server
  • 较多数据,-XX:+TieredCompilation < server < client
  • 大量数据,-XX:+TieredCompilation < server < client

通过上面我们知道,分层编译是批量处理的最佳方式。

长时间运行

长时间运行,其实应该是你的应用经过了热身,对于热点代码进行了重新编译之后,我们来看看他们分别的吞吐量如何:

  • 热身极少时间,client < server < -XX:+TieredCompilation
  • 热身较多时间,client < server < -XX:+TieredCompilation
  • 热身大量时间,client < server ≈ -XX:+TieredCompilation

从上面我们能够知道,其实无论时间的长短,client的吞吐量并不会有太大的波动。但是client的吞吐量都小于另外两种,而当时间足够长的情况下,server和分层编译的吞吐量基本相同。

所以长时间运行的应用可以使用 server 或者 -XX:+TieredCompilation 。