不幸的是,我正在研究JIT编译器如何工作的模糊回忆,并且找不到合适的文档.我能找到的最好的是来自IBM的优化过程的brief outline.
在我养成实施基于断言的测试的习惯之前,我想知道是否有最佳实践来最小化它们对性能的影响.我讨厌实施一系列测试只是为了发现它们的集体效果是大幅降低性能,即使它们的影响可以忽略不计.
您是否可以告诉我以下几行是否会拖累生产版本的性能(默认情况下禁用“断言”)?
for (T obj : Collection){ assert obj.someProperty(); }
如果我有更复杂的东西,包括仅用于断言的短期对象,该怎么办呢?
TreeMap<Integer,T> map = new TreeMap<>(); int i = 0; for (T obj : Collection){ map.put(i,obj); assert obj.someProperty(); i++; } // assert something about map,then never use it again
提前致谢!
Oracle关于“assert”声明的文档的相关摘录:
Removing all Trace of Assertions from Class Files Programmers
developing applications for resource-constrained devices may wish to
strip assertions out of class files entirely. While this makes it
impossible to enable assertions in the field,it also reduces class
file size,possibly leading to improved class loading performance. In
the absence of a high quality JIT,it could lead to decreased
footprint and improved runtime performance.The assertion facility offers no direct support for stripping
assertions out of class files. The assert statement may,however,be
used in conjunction with the “conditional compilation” idiom described
in the Java Language Specification,enabling the compiler to eliminate
all traces of these asserts from the class files that it generates:static final boolean asserts = … ; // false to eliminate asserts
if (asserts) assert ;
并从FAQ部分:
Why not provide a compiler flag to completely eliminate assertions
from object files? It is a firm requirement that it be possible to
enable assertions in the field,for enhanced serviceability. It would
have been possible to also permit developers to eliminate assertions
from object files at compile time. Assertions can contain side
effects,though they should not,and such a flag could therefore alter
the behavior of a program in significant ways. It is viewed as good
thing that there is only one semantics associated with each valid Java
program. Also,we want to encourage users to leave asserts in object
files so they can be enabled in the field. Finally,the spec demands
that assertions behave as if enabled when a class runs before it is
initialized. It would be impossible to offer these semantics if
assertions were stripped from the class file. Note,that the
standard “conditional compilation idiom” described in the Java
Language Specification can be used to achieve this effect for
developers who really want it.
解决方法
private static boolean testSomePropertyTrue(Collection<T> collection) { boolean test = true; for (T obj : collection){ test = test && obj.someProperty(); } return test; }
…
assert testSomePropertyTrue(collection);
这使得JIT优化的代码没有任何歧义,并且当启用断言时将执行相同的不变检查.
如上所述,无论断言是否已启用,您的第二个示例将始终创建TreeMap.将整个事物包装在函数中并将其作为单个断言进行评估将在运行时完全消除该代码路径.
就像这个问题的另一个答案所示,断言将留下字节码,无论它们是否被启用,但使用上面显示的样式将确定性地阻止这些代码路径执行,除非启用断言.