自动装箱原始文字是否有性能成本?
Is there a performance cost to autobox a primitive literal?
假设我有以下代码:
Map<String, Boolean> map = ...
map.put("foo", true);
理论上,true
必须自动装箱,与插入 Boolean.TRUE
相比,性能会受到轻微影响。但是由于我们处理的是文字值,编译器是否可以用盒装文字替换原始文字,这样就没有额外的运行时开销?
在有人攻击我之前,为了代码清晰起见,我通常会选择原始文字,即使性能成本很小。这个问题主要是理论性的。
是的,对性能的影响很小。为了装箱一个基元,使用了包装器类型的 valueOf()
方法。因为这是 Boolean
(return x ? TRUE : FALSE;
) 的简单方法,所以 JIT 可能能够有效地内联结果;然而,目前 Java 编译器没有。 (JLS 不需要使用 valueOf()
,因此可以引入对 Boolean
的优化。)
对于其他类型,它更复杂。例如,Integer
returns 为接近零的值缓存实例,并为更大的值创建新实例。优化仍然可以执行,但分配一个新实例总是需要一些时间。
针对评论,让我把重点放在我认为是问题重点的地方:
since we're dealing with a literal value, is it possible for the compiler to replace the primitive literal with a boxed literal
是的,可能,但是不,Oracle javac
编译器不这样做。
重要吗?不,拳击到 Boolean
的性能损失是无穷小的;装箱 boolean
使用与其他基元相同的 valueOf()
技术对编译器来说是一个安全而明智的选择。
假设我有以下代码:
Map<String, Boolean> map = ...
map.put("foo", true);
理论上,true
必须自动装箱,与插入 Boolean.TRUE
相比,性能会受到轻微影响。但是由于我们处理的是文字值,编译器是否可以用盒装文字替换原始文字,这样就没有额外的运行时开销?
在有人攻击我之前,为了代码清晰起见,我通常会选择原始文字,即使性能成本很小。这个问题主要是理论性的。
是的,对性能的影响很小。为了装箱一个基元,使用了包装器类型的 valueOf()
方法。因为这是 Boolean
(return x ? TRUE : FALSE;
) 的简单方法,所以 JIT 可能能够有效地内联结果;然而,目前 Java 编译器没有。 (JLS 不需要使用 valueOf()
,因此可以引入对 Boolean
的优化。)
对于其他类型,它更复杂。例如,Integer
returns 为接近零的值缓存实例,并为更大的值创建新实例。优化仍然可以执行,但分配一个新实例总是需要一些时间。
针对评论,让我把重点放在我认为是问题重点的地方:
since we're dealing with a literal value, is it possible for the compiler to replace the primitive literal with a boxed literal
是的,可能,但是不,Oracle javac
编译器不这样做。
重要吗?不,拳击到 Boolean
的性能损失是无穷小的;装箱 boolean
使用与其他基元相同的 valueOf()
技术对编译器来说是一个安全而明智的选择。