Я пытаюсь протестировать две разные реализации функции Java, которая проверяет, содержит ли число хотя бы одну четную цифру. В первой реализации используется рукописный цикл, а во второй - stream.
public class StreamTest {
public boolean containsEvenDigit(int n) {
char [] digits = String.valueOf(n).toCharArray();
for(char d : digits) {
if (d % 2 == 0) {
return true;
}
}
return false;
}
public boolean containsEvenDigitStreams(int n) {
return String.valueOf(n).chars().anyMatch(i -> i % 2 == 0);
}
public static void main(String[] args) {
System.out.println("============WITHOUT STREAM=========== = ");
long start1 = System.nanoTime();
for(int i = 0 ; i < 1_000_000; i++) {
(new StreamTest()).containsEvenDigit(11215 + i);
}
long duration1 = (long)(System.nanoTime() - start1)/1_000_000;
System.out.println("Duration : " + duration1 + " milliseconds.");
System.out.println();
System.out.println("============USING STREAM=========== = ");
long start2 = System.nanoTime();
for(int i = 0 ; i < 1_000_000; i++) {
(new StreamTest()).containsEvenDigitStreams(11215 + i);
}
long duration2 = (long)(System.nanoTime() - start2)/1_000_000;
System.out.println("Duration : " + duration2 + " milliseconds.");
System.out.println();
}
}
В функции main я не выводю возвращаемые значения тестируемых функций, чтобы исключить накладные расходы ввода-вывода. Результат показывает, что реализация с использованием потоков выполняется намного медленнее, чем реализация с использованием цикла.
============WITHOUT STREAM============
Duration : 119 milliseconds.
============USING STREAM============
Duration : 771 milliseconds.
Означает ли это, что потоки Java 8 медленнее, чем циклы, написанные вручную?
Обновлять: Сейчас я использую JMH для тестирования двух функций.
public class MyBenchmark {
private boolean containsEvenDigit(int n) {
char [] digits = String.valueOf(n).toCharArray();
for(char d : digits) {
if (d % 2 == 0) {
return true;
}
}
return false;
}
private boolean containsEvenDigitStream(int n) {
return String.valueOf(n).chars().anyMatch(i -> i % 2 == 0);
}
@State(Scope.Thread)
public static class MyState{
public int x = 1_357_997_531;
}
@Benchmark
public void testLoop(MyState state, Blackhole blackhole) {
boolean retVal = containsEvenDigit(state.x);
blackhole.consume(retVal);
}
@Benchmark
public void testStream(MyState state, Blackhole blackhole) {
boolean retVal = containsEvenDigitStream(state.x);
blackhole.consume(retVal);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
На этот раз рукописный цикл превосходит поток примерно на 8. Вот сводка результатов.
Benchmark Mode Cnt Score Error Units
MyBenchmark.testLoop thrpt 200 3578620.170 ± 207106.919 ops/s
MyBenchmark.testStream thrpt 200 433884.589 ± 23993.270 ops/s
в одном методе вы используете toCharArray(), а в другом - chars(), как узнать, нет ли разницы? вам нужно предоставить один и тот же аргумент для двух методов для тестирования
Это не то же самое, что stackoverflow.com/q/504103/802339. Я спросил, медленнее ли потоки Java 8, а не о написании безупречного теста.
См .: jaxenter.com/…
@sank Если вы напишете «Я пытаюсь сравнить две разные реализации», вполне ожидаемо, что кто-то укажет вам, как правильно написать этот тест. Если вы напишете правильно, у вас есть ответ.
У меня есть еще один дубликат, который спрашивает когда, поток будет медленнее, чем цикл. И краткий ответ ... это сложно и зависит от версии Java.
@StephenC Сейчас я тестирую тесты с помощью JMH. Результаты такие же.
ОК. Теперь как иметь единую «точку данных». Это говорит о том, что для этого конкретного примера (закодированного так, как вы это сделали) реализация цикла выполняется быстрее, чем реализация потока. Но вы не можете сделать обобщение на основе одной точки данных / одного примера до вывода, который пытаетесь сделать. Итак, еще раз, нет, это не значит.




См .: stackoverflow.com/questions/504103