假设我有一个 java.util.Collection 想要循环。通常我会这样做:
for(Thing thing : things) do_something_with(thing);
Run Code Online (Sandbox Code Playgroud)
但是假设这是在一些到处使用的核心实用方法中,并且在大多数地方,集合是空的。那么理想情况下,我们不希望仅仅为了执行无操作循环而对每个调用者强加迭代器分配,并且我们可以重写如下内容:
if(things.isEmpty()) return;
for(Thing thing : things) do_something_with(thing);
Run Code Online (Sandbox Code Playgroud)
如果是列表,则更极端的选择things是使用 C 样式for循环。
但是等等,Java 转义分析应该消除这种分配,至少在 C2 编译器处理此方法之后。所以应该不需要这种“纳米优化”。(我什至不会用微优化这个词来形容它;它对于这个来说有点太小了。)除了......
我一直听说逃逸分析是“脆弱的”,但似乎没有人谈论过什么会导致它变得混乱。直觉上,我认为更复杂的控制流将是最值得担心的,这意味着 for-each 循环中的迭代器应该被可靠地消除,因为那里的控制流很简单。
这里的标准响应是尝试进行实验,但除非我知道其中的变量,否则很难相信我可能想从这样的实验中得出的任何结论。
事实上,在这篇博客文章中,有人尝试了这样的实验,三分之二的分析器给出了错误的结果:
http://psy-lob-saw.blogspot.com/2014/12/the-escape-of-arraylistiterator.html
我对晦涩难懂的 JVM 魔法的了解比该博客文章的作者要少得多,而且很可能更容易被误导。
我正在对MPEG解码器进行一些优化.为了确保我的优化没有破坏任何东西,我有一个测试套件,对整个代码库(优化和原始代码库)进行基准测试,并验证它们是否产生相同的结果(基本上只是通过解码器和crc32提供几个不同的流)输出).
在Sun 1.6.0_18中使用"-server"选项时,测试套件在预热后的优化版本上运行速度降低约12%(与默认的"-client"设置相比),而原始代码库获得了良好的提升运行速度是客户端模式的两倍.
虽然起初这对我来说似乎只是一个热身问题,但我添加了一个循环来多次重复整个测试套件.然后,对于从测试的第3次迭代开始的每次传递,执行时间变为常量,优化版本仍然比客户端模式慢12%.
我也很确定它不是垃圾收集问题,因为代码在启动后绝对没有对象分配.代码主要包括一些位操作操作(流解码)和大量基本浮动数学(生成PCM音频).涉及的唯一JDK类是ByteArrayInputStream(将流提供给测试并从测试中排除磁盘IO)和CRC32(以验证结果).我也观察到与Sun JDK 1.7.0_b98相同的行为(只有15%而不是12%).哦,测试都是在同一台机器(单核)上完成的,没有运行其他应用程序(WinXP).虽然测量的执行时间存在一些不可避免的变化(使用System.nanoTime btw),但使用相同设置的不同测试运行之间的差异从未超过2%,通常低于1%(预热后),
是否有任何已知的编码模式在服务器JIT上表现更差?如果做不到这一点,有什么选择可以"偷看"引擎盖并观察JIT在那里做什么?
也许我误解了我的"热身"描述.没有明确的预热代码.整个测试套件(包括12个不同的MPEG流,包含〜180K音频帧总)被执行10次,我认为该第一3个运行为"预热".在我的机器上进行一轮测试需要大约40秒的100%cpu.
我按照建议玩了JVM选项并使用"-Xms512m -Xmx512m -Xss128k -server -XX:CompileThreshold = 1 -XX:+ PrintCompilation -XX:+ AggressiveOpts -XX:+ PrintGC"我可以验证所有编译都发生在前3轮.垃圾收集每3-4轮踢一次,最多耗时40ms(512m非常超大,因为测试可以用16米就好了).由此我得出结论,垃圾收集在这里没有影响.不过,比较客户端与服务器(其他选项未改变)仍有12/15%的差异.
我看了这篇文章.看起来很好.然而,当HotSpot(不依赖于服务器或客户端或不依赖Sun版本)使代码内联时,作者或其他有意识的人会告诉我编码技巧.
我已经对下面的代码进行了微观基准测试,我注意到一些有趣的东西,我希望有人可以更多地了解它.它导致一种情况,它看起来像一个for循环可以继续运行,同时阻止JVM中的其他线程.如果这是真的那么我想理解为什么,如果它不是真的那么任何洞察我可能遗失的东西将不胜感激.
为了建立这种情况,让我引导您完成我正在运行的基准测试及其结果.
代码非常简单,迭代数组中的每个元素,对其内容求和.重复'targetCount'次.
public class UncontendedByteArrayReadBM extends Benchmark {
private int arraySize;
private byte[] array;
public UncontendedByteArrayReadBM( int arraySize ) {
super( "array reads" );
this.arraySize = arraySize;
}
@Override
public void setUp() {
super.setUp();
array = new byte[arraySize];
}
@Override
public void tearDown() {
array = null;
}
@Override
public BenchmarkResult invoke( int targetCount ) {
long sum = 0;
for ( int i=0; i<targetCount; i++ ) {
for ( int j=0; j<arraySize; j++ ) {
sum += array[j]; …Run Code Online (Sandbox Code Playgroud) 是否可以在运行时更改Java JVM(JIT)的选项和/或模式?例如,更改XX:CompileThreshold,甚至在解释和编译的代码之间切换(-Xcompvs -Xint).
我的JVM来自OpenJDK(1.6),Hotspot或Zero/Shark
我已经运行了很多实验(几个月的cpu时间),在我的日志中有以下警告:
Java HotSpot(TM)64位服务器VM警告:共享内存文件的空间不足
实验终止没有错误,但现在我想知道我可能,也可能不会从他们那里评估.所以:
Java HotSpot中共享内存文件空间不足的影响是什么?
细节:
我找到的关于共享内存文件的所有内容都是http://openjdk.java.net/groups/hotspot/docs/Serviceability.html.从这看起来,共享内存文件的缺乏似乎对我的实验影响不大:)我不使用分析器等来评估我的实验,而只使用我已成功创建的日志文件.
我测量函数foo()调用的频率.缺少共享内存文件会改变我的程序的功能行为,所以我不应该从实验中评估这个吗?
此外,我测量运行时和内存要求.JVM的性能是否发生变化,以至于我不应该从实验中评估这一点?
最后,我有实验,我运行我的算法的分布式版本.JVM的性能是否会发生强烈变化,如果某些但不是所有并行实例的共享内存文件丢失,则并行功能行为会发生变化?
是否有任何实用程序或脚本(使用java或本机代码)查看JDK 8 HotSpot JVM中字符串池中存在的所有字符串的列表,而不会对JVM产生很多性能影响?
或者,只要将新字符串添加到JVM中,我是否可以将侦听器连接起来?
谢谢,哈里什
默认情况下,JVM中有一组可用的系统属性,如此处所述.热点在哪里派生?
user.home必须在不同的操作系统上以不同的方式确定属性,我正在寻找执行此操作的代码.
在Java 8之前,我们有5个主要的运行时数据区域:
在Java 8中,没有Perm Gen,这意味着不再有“ java.lang.OutOfMemoryError:PermGen”
很棒,但我也读过
方法区域是Perm Gen中空间的一部分
但我似乎找不到任何明确表明Java 8中不再存在“方法”区域的内容。
因此删除了Perm Gen以及Method区域,或者仅删除了Perm Gen且Method区域仍然存在于旧一代中。
请附上您可能看到的与Java 8内存模型相关的任何良好的源材料
我有一个简单的演示来检查JVM内存分配和释放的详细信息。
Java版本
$ java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
Run Code Online (Sandbox Code Playgroud)
演示
/**
* VM Options: -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
*/
public class DefaultCollector {
private static final int _1MB = 1024 * 1024;
public static void main(String... args) {
byte[] arr1 = new byte[2 * _1MB];
byte[] arr2 = new byte[2 * _1MB];
byte[] arr3 = new byte[2 * _1MB];
byte[] arr4 = new byte[4 * …Run Code Online (Sandbox Code Playgroud) jvm-hotspot ×10
java ×9
jvm ×8
java-8 ×2
jit ×2
performance ×2
inline ×1
measurement ×1
string ×1
warnings ×1