Ответ нацелен на комментарий @Riaan по константам и перечислениям метода и причинам производительности, и он не отвечает непосредственно на вопрос OP, поэтому я думаю, что это можно считать шумом.Тем не менее, я считаю, что важно понять, как работает внутреннее устройство.
Я взял эталонный тест из его примера и улучшил его, удалив сборку мусора и создание строк, которые занимают более 90% времени выполнения.Добавлена фаза прогрева, чтобы гарантировать, что горячая точка на самом деле компилирует методы.
Есть еще кое-что, эталонным тестом является тестирование на месте вызова.Оптимизация для сайтов вызовов довольно различна для 1, для 2 для немногих больше и для больше-больше.CallSite - это вызов абстрактного (или просто переопределенного) метода.
Ниже приведен тест с 6 константами перечислений:
package t1;
public class ZEnums {
public enum MyEnum {
A { boolean getBooleanValue(){ return true; }},
B { boolean getBooleanValue(){ return true; }},
C { boolean getBooleanValue(){ return false; }},
D { boolean getBooleanValue(){ return false; }},
E { boolean getBooleanValue(){ return false; }},
F { boolean getBooleanValue(){ return false; }},
;
abstract boolean getBooleanValue();
}
public enum MyEnumAlt {
A (true),
B (true),
C (false),
D (false),
E (false),
F (false),
;
private final boolean isTrue;
MyEnumAlt( boolean isTrue){ this.isTrue = isTrue; }
boolean getBooleanValue(){ return isTrue; };
}
public static void main(String[] args) {
log("Warming up...");
//10k iterations won't do since not all paths for MyEnum are invoked 10k (default) times to warrant compilations
long warmum = testEnum(100000 )+ testAlt(100000)+testEnum(100000 )+ testAlt(100000);
log("Warm up: %d", warmum);
//no info from +XX:+PrintCompilation below this one, or the test is invalid
testMain();
}
public static void testMain() {
int iterations = (int)4e7;
log("Testing %d iterations%n", iterations);
log("====");
log("Testing with Overridden method...");
System.gc();
{
long start = System.currentTimeMillis();
long len = 0;
len = testEnum(iterations);
long time = System.currentTimeMillis()-start;
log("Overridden method version took %dms, length: %d ", time, len);
}
////////////
System.gc();
{
log("Testing with Constant in c-tor... ");
long start = System.currentTimeMillis();
long len = testAlt(iterations);
long time = System.currentTimeMillis()-start;
log("Constant in c-tor version took %dms, length: %d ", time, len);
}
}
private static long testEnum(int iterations) {
long len = 0;
for(int i=0; i<iterations; i++){
MyEnum tmpEnum = MyEnum.A;
if(i%3==0){ tmpEnum = MyEnum.A;
}else if(i%4==0){ tmpEnum = MyEnum.B;
}else if(i%5==0){ tmpEnum = MyEnum.C;
}else if(i%6==0){ tmpEnum = MyEnum.D;
}else if(i%6==0){ tmpEnum = MyEnum.E;
}else{ tmpEnum = MyEnum.F;
}
String tmp = tmpEnum.getBooleanValue()?"XXX":"ABCDE";
len+=tmp.length();
}
return len;
}
private static long testAlt(int iterations) {
long len =0;
for(int i=0; i<iterations; i++){
MyEnumAlt tmpEnum = MyEnumAlt.A;
if(i%3==0){ tmpEnum = MyEnumAlt.A;
}else if(i%4==0){ tmpEnum = MyEnumAlt.B;
}else if(i%5==0){ tmpEnum = MyEnumAlt.C;
}else if(i%6==0){ tmpEnum = MyEnumAlt.D;
}else if(i%6==0){ tmpEnum = MyEnumAlt.E;
}else{ tmpEnum = MyEnumAlt.F;
}
String tmp = tmpEnum.getBooleanValue()?"XXX":"ABCDE";
len+=tmp.length();
}
return len;
}
static void log(String msg, Object... params){
String s = params.length>0?String.format(msg, params):msg;
System.out.printf("%tH:%<tM:%<tS.%<tL %s%n", new Long(System.currentTimeMillis()), s);
}
}
21:08:46.685 Warming up...
148 1% t1.ZEnums::testEnum @ 7 (125 bytes)
150 1 t1.ZEnums$MyEnum$6::getBooleanValue (2 bytes)
152 2 t1.ZEnums$MyEnum$1::getBooleanValue (2 bytes)
154 3 t1.ZEnums$MyEnum$2::getBooleanValue (2 bytes)
155 4 t1.ZEnums$MyEnum$3::getBooleanValue (2 bytes)
158 2% t1.ZEnums::testAlt @ 7 (125 bytes)
162 5 t1.ZEnums::testEnum (125 bytes)
164 6 t1.ZEnums::testAlt (125 bytes)
21:08:46.716 Warm up: 1600000
21:08:46.716 Testing 40000000 iterations
21:08:46.716 ====
21:08:46.716 Testing with Overridden method...
21:08:47.513 <b>Overridden method version took 781ms</b>, length: 160000000
21:08:47.513 Testing with Constant in c-tor...
21:08:48.138 <b>Constant in c-tor version took 625ms</b>, length: 160000000
Код был запущен с -server -XX:+PrintCompilation
опции.Разница не огромная, конечно.Однако это не интересная проблема.Если вы протестируете версию с двумя константами перечисления, результат может значительно отличаться.Для двух сайтов вызовов компилятор генерирует код путем встраивания рассматриваемого метода.В приведенном выше тесте это удалит весь вызов booleanValue и может даже заставить выполнить тест в O (1).
Однако самая смешная часть состоит из 2–3 констант перечисления, когда компилятор начинает использовать встроенные кэши.а затем константа и WOW magic все меняется.
Суть в том, что правильный тест действительно труден и требует определенных знаний о том, как JIT компилируется, когда GC может быть проблемой (либо удалить ее, либо принять), и так далее. Ссылки :