keo*_*eos 1 java compiler-construction enums
考虑这种情况:
STYLE1:
static enum Style1{
FIRE_BALL {
@Override
public boolean isCold() {
return false;
}
},ICE_BALL {
@Override
public boolean isCold() {
return true;
}
},FIRE_ARROW {
@Override
public boolean isCold() {
return false;
}
},ICE_ARROW {
@Override
public boolean isCold() {
return true;
}
};
public abstract boolean isCold();
}
Run Code Online (Sandbox Code Playgroud)
蓝紫魅力:
static enum Style2{
FIRE_BALL,ICE_BALL,FIRE_ARROW,ICE_ARROW;
public boolean isCold(){
//return this.toString().contains("ICE")?true:false; //sorry
return this.toString().contains("ICE");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我只是想知道它是否冷.所以我要问:
编译器可以知道目标结果和常量折叠Style2吗?
如果没有,Style1应该显然更快,但更冗长.假设这是更复杂的情况,并且有更多的组合,例如BIG_FIRE_SLOW_BALL与isFast(),isBig(),Style1将以代码块结束.
所以我用jmh和jUnit做了一些测试:
与jmh:
@Benchmark
public boolean testStyle1() {
return Style1.values()[ThreadLocalRandom.current().nextInt(4)].isCold();
}
@Benchmark
public boolean testStyle2() {
return Style2.values()[ThreadLocalRandom.current().nextInt(4)].isCold();
}
Run Code Online (Sandbox Code Playgroud)
设置时:
.warmupIterations(10)
.measurementIterations(10)
.threads(8)
Benchmark Mode Cnt Score Error Units
EnumTest1.testStyle1 avgt 10 34.057 ± 0.101 ns/op
EnumTest1.testStyle2 avgt 10 36.196 ± 0.453 ns/op
Run Code Online (Sandbox Code Playgroud)
好吧,将线程数设置为1
.threads(1)
Benchmark Mode Cnt Score Error Units
EnumTest1.testStyle1 avgt 10 34.306 ± 11.692 ns/op
EnumTest1.testStyle2 avgt 10 44.279 ± 11.103 ns/op
Run Code Online (Sandbox Code Playgroud)
因此,看起来Style2无法通过编译器进行优化.
2,用jUnit:
private static final int LOOP_TIMES = 100000000;
private static final Random random1=new Random(47);
private static final Random random2=new Random(47);
@Test
public void testStyle1() {
int cnt = 0;
for (int i = 0; i < LOOP_TIMES; i++) {
if(Style1.values()[random1.nextInt(4)].isCold()){
cnt++;
}
}
System.out.println(cnt);
}
@Test
public void testStyle2() {
int cnt = 0;
for (int i = 0; i < LOOP_TIMES; i++) {
if(Style2.values()[random2.nextInt(4)].isCold()){
cnt++;
}
}
System.out.println(cnt);
}
Run Code Online (Sandbox Code Playgroud)
结果:
Time: 1 2 3 inverse order 4 5 6
Style1: 3.631s 4.578s 3.754s Style2 4.131s 5.487s 4.261s
Style2: 2.559s 4.216s 3.155s Style1 2.316s 3.977s 4.152s
Run Code Online (Sandbox Code Playgroud)
因此,Style1可能会更快.
但为什么两个结果很接近,特别是当我同时用jmh进行测试时?或者我们应该如何处理这个?
也许给Style1一些字段来存储每个结果可能会减少冗余.但我仍觉得不太满意.希望你们中的一些人能告诉我更多.
非常感谢你们.@Andy举了一个很好的例子,我在这里添加:
enum Style4{
FIRE_BALL,
ICE_BALL,
FIRE_ARROW,
ICE_ARROW;
private boolean cold;
private Style4(){
this.cold = this.toString().contains("ICE");
}
public boolean isCold(){
return cold;
}
}
Run Code Online (Sandbox Code Playgroud)
这第四种风格无需提及真或假.
如果使用构造函数,可以在某种程度上改进style1的详细程度.这将是快速的,并且(在我看来)更容易阅读.
enum Style1{
FIRE_BALL(false),
ICE_BALL(true),
FIRE_ARROW(false),
ICE_ARROW(true);
private final cold;
private Style1(boolean cold){
this.cold = cold;
}
public boolean isCold(){
return cold;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这三种样式中的任何一种都不可能成为代码中的热点.编写更易于阅读的代码并在以后根据需要调整性能更为重要.
| 归档时间: |
|
| 查看次数: |
102 次 |
| 最近记录: |