Ответ 1
UPDATE
Несколько комментариев, интересующихся, был ли мой бенчмарк внизу испорчен - после введения большого количества случайности (чтобы JIT не мог оптимизировать слишком много вещей), я все равно получаю похожие результаты, поэтому я склонен думать, что все в порядке.
Тем временем я встретил эту презентацию командой лямбда-реализации. На рисунках 16 показаны некоторые показатели производительности: внутренние классы и блокировки имеют аналогичную производительность/неконвертируемость лямбда в 5 раз быстрее.
И @StuartMarks разместили эту очень интересную ссылку, которая анализирует производительность лямбда. Суть в том, что компиляция пост JIT, lambdas и анонимные классы аналогичным образом выполняются в текущих реализациях JVM Hostpot.
ВАШ ЭТАЛОН
Я также проверил ваш тест, когда вы его разместили. Проблема в том, что он работает всего за 20 мс для первого метода и 2 мс для второго. Хотя это соотношение 10: 1, оно никоим образом не является репрезентативным, потому что время измерения слишком мало.
Затем я изменил ваш тест, чтобы разрешить больше прогревания JIT, и получаю аналогичные результаты, как с jmh (т.е. никакой разницы между анонимным классом и лямбдой).
public class Main {
static interface ICallback {
void payload();
}
static void measureAnonymousClass() {
final int arr[] = {0};
ICallback clb = new ICallback() {
@Override
public void payload() {
arr[0]++;
}
};
clb.payload();
}
static void measureLambda() {
final int arr[] = {0};
ICallback clb = () -> {
arr[0]++;
};
clb.payload();
}
static void runTimed(String message, Runnable act) {
long start = System.nanoTime();
for (int i = 0; i < 10_000_000; i++) {
act.run();
}
long end = System.nanoTime();
System.out.println(message + ":" + (end - start));
}
public static void main(String[] args) {
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
}
}
Последний запуск занимает около 28 секунд для обоих методов.
JMH MICRO BENCHMARK
Я пропустил тот же тест с jmh, и в нижней строке указано, что четыре метода занимают столько же времени, сколько и эквивалент:
void baseline() {
arr[0]++;
}
Другими словами, JIT включает как анонимный класс, так и лямбда, и они принимают ровно одно и то же время.
Итоговый результат:
Benchmark Mean Mean error Units
empty_method 1.104 0.043 nsec/op
baseline 2.105 0.038 nsec/op
anonymousWithArgs 2.107 0.028 nsec/op
anonymousWithoutArgs 2.120 0.044 nsec/op
lambdaWithArgs 2.116 0.027 nsec/op
lambdaWithoutArgs 2.103 0.017 nsec/op