java java-stream benchmarking jmh java-12

Resultado desconcertante de microbenchmark para la API de flujo en Java 12 en comparación con Java 8 con-gc true



java-stream benchmarking (1)

Gracias a todos por la ayuda y especialmente a @Aleksey Shipilev!

Después de los cambios aplicados en el punto de referencia JMH, los resultados parecen más realistas (?)

Cambios:

  1. Cambie el método de configuración que se ejecutará antes / después de cada iteración del punto de referencia.

    @Setup(Level.Invocation) -> @Setup(Level.Iteration)

  2. Detener JMH forzando GC entre iteraciones. Forzar el GC completo antes de cada iteración es muy probable que se deshaga de las heurísticas del GC. (c) Aleksey Shipilev

    -gc true -> -gc false

Nota: gc false por defecto.

Tablas de comparacion

Sobre la base de los nuevos puntos de referencia de rendimiento, no hay degradación del rendimiento en Java 12 en comparación con Java 8.

Nota: Después de esos cambios, el error de rendimiento para un tamaño de matriz pequeño aumentó significativamente en más del 100%, para un conjunto de datos grande sigue siendo el mismo.

Resultados crudos

Java 8

# Run complete. Total time: 04:36:29 Benchmark (arraySize) Mode Cnt Score Error Units FilterBenchmark.complexFilter 10 thrpt 50 5947577.648 ± 257535.736 ops/s FilterBenchmark.complexFilter 100 thrpt 50 3131081.555 ± 72868.963 ops/s FilterBenchmark.complexFilter 1000 thrpt 50 489666.688 ± 6539.466 ops/s FilterBenchmark.complexFilter 10000 thrpt 50 17297.424 ± 93.890 ops/s FilterBenchmark.complexFilter 100000 thrpt 50 1398.702 ± 72.820 ops/s FilterBenchmark.complexFilter 1000000 thrpt 50 81.309 ± 0.547 ops/s FilterBenchmark.complexFilterParallel 10 thrpt 50 24515.743 ± 450.363 ops/s FilterBenchmark.complexFilterParallel 100 thrpt 50 25584.773 ± 290.249 ops/s FilterBenchmark.complexFilterParallel 1000 thrpt 50 24313.066 ± 425.817 ops/s FilterBenchmark.complexFilterParallel 10000 thrpt 50 11909.085 ± 51.534 ops/s FilterBenchmark.complexFilterParallel 100000 thrpt 50 3260.864 ± 522.565 ops/s FilterBenchmark.complexFilterParallel 1000000 thrpt 50 406.297 ± 96.590 ops/s FilterBenchmark.multipleFilters 10 thrpt 50 3785766.911 ± 27971.998 ops/s FilterBenchmark.multipleFilters 100 thrpt 50 1806210.041 ± 11578.529 ops/s FilterBenchmark.multipleFilters 1000 thrpt 50 211435.445 ± 28585.969 ops/s FilterBenchmark.multipleFilters 10000 thrpt 50 12614.670 ± 370.086 ops/s FilterBenchmark.multipleFilters 100000 thrpt 50 1228.127 ± 21.208 ops/s FilterBenchmark.multipleFilters 1000000 thrpt 50 99.149 ± 1.370 ops/s FilterBenchmark.multipleFiltersParallel 10 thrpt 50 23896.812 ± 255.117 ops/s FilterBenchmark.multipleFiltersParallel 100 thrpt 50 25314.613 ± 169.724 ops/s FilterBenchmark.multipleFiltersParallel 1000 thrpt 50 23113.388 ± 305.605 ops/s FilterBenchmark.multipleFiltersParallel 10000 thrpt 50 12676.057 ± 119.555 ops/s FilterBenchmark.multipleFiltersParallel 100000 thrpt 50 3373.367 ± 211.108 ops/s FilterBenchmark.multipleFiltersParallel 1000000 thrpt 50 477.870 ± 70.878 ops/s FilterBenchmark.oldFashionFilters 10 thrpt 50 45874144.758 ± 2210325.177 ops/s FilterBenchmark.oldFashionFilters 100 thrpt 50 4902625.828 ± 60397.844 ops/s FilterBenchmark.oldFashionFilters 1000 thrpt 50 662102.438 ± 5038.465 ops/s FilterBenchmark.oldFashionFilters 10000 thrpt 50 29390.911 ± 257.311 ops/s FilterBenchmark.oldFashionFilters 100000 thrpt 50 1999.032 ± 6.829 ops/s FilterBenchmark.oldFashionFilters 1000000 thrpt 50 200.564 ± 1.695 ops/s

Java 12

# Run complete. Total time: 04:36:20 Benchmark (arraySize) Mode Cnt Score Error Units FilterBenchmark.complexFilter 10 thrpt 50 10338525.553 ? 1677693.433 ops/s FilterBenchmark.complexFilter 100 thrpt 50 4381301.188 ? 287299.598 ops/s FilterBenchmark.complexFilter 1000 thrpt 50 607572.430 ? 9367.026 ops/s FilterBenchmark.complexFilter 10000 thrpt 50 30643.286 ? 472.033 ops/s FilterBenchmark.complexFilter 100000 thrpt 50 1450.341 ? 3.730 ops/s FilterBenchmark.complexFilter 1000000 thrpt 50 138.996 ? 2.052 ops/s FilterBenchmark.complexFilterParallel 10 thrpt 50 21289.444 ? 183.245 ops/s FilterBenchmark.complexFilterParallel 100 thrpt 50 20105.239 ? 124.759 ops/s FilterBenchmark.complexFilterParallel 1000 thrpt 50 19418.830 ? 141.664 ops/s FilterBenchmark.complexFilterParallel 10000 thrpt 50 13874.585 ? 104.418 ops/s FilterBenchmark.complexFilterParallel 100000 thrpt 50 5334.947 ? 25.452 ops/s FilterBenchmark.complexFilterParallel 1000000 thrpt 50 781.046 ? 9.687 ops/s FilterBenchmark.multipleFilters 10 thrpt 50 5460308.048 ? 478157.935 ops/s FilterBenchmark.multipleFilters 100 thrpt 50 2227583.836 ? 113078.932 ops/s FilterBenchmark.multipleFilters 1000 thrpt 50 287157.190 ? 1114.346 ops/s FilterBenchmark.multipleFilters 10000 thrpt 50 16268.016 ? 704.735 ops/s FilterBenchmark.multipleFilters 100000 thrpt 50 1531.516 ? 2.729 ops/s FilterBenchmark.multipleFilters 1000000 thrpt 50 123.881 ? 1.525 ops/s FilterBenchmark.multipleFiltersParallel 10 thrpt 50 20403.993 ? 147.247 ops/s FilterBenchmark.multipleFiltersParallel 100 thrpt 50 19426.222 ? 96.979 ops/s FilterBenchmark.multipleFiltersParallel 1000 thrpt 50 17692.433 ? 67.606 ops/s FilterBenchmark.multipleFiltersParallel 10000 thrpt 50 12108.482 ? 34.500 ops/s FilterBenchmark.multipleFiltersParallel 100000 thrpt 50 3782.756 ? 22.044 ops/s FilterBenchmark.multipleFiltersParallel 1000000 thrpt 50 589.972 ? 71.448 ops/s FilterBenchmark.oldFashionFilters 10 thrpt 50 41024334.062 ? 1374663.440 ops/s FilterBenchmark.oldFashionFilters 100 thrpt 50 6011852.027 ? 246202.642 ops/s FilterBenchmark.oldFashionFilters 1000 thrpt 50 553243.594 ? 2217.912 ops/s FilterBenchmark.oldFashionFilters 10000 thrpt 50 29188.753 ? 580.958 ops/s FilterBenchmark.oldFashionFilters 100000 thrpt 50 2061.738 ? 8.456 ops/s FilterBenchmark.oldFashionFilters 1000000 thrpt 50 196.105 ? 3.203 ops/s

Como parte de mi investigación sobre la diferencia entre usar un filtro complejo o varios filtros en secuencias, observo que el rendimiento en Java 12 es mucho más lento que en Java 8.

¿Hay alguna explicación para esos resultados extraños? ¿Me perdí algo aquí?

Configuración:

  • java 8

    • OpenJDK Runtime Environment (compilación 1.8.0_181-8u181-b13-2 ~ deb9u1-b13)
    • VM de servidor OpenJDK de 64 bits (compilación 25.181-b13, modo mixto)
  • java 12

    • OpenJDK Runtime Environment (compilación 12 + 33)
    • OpenJDK 64-Bit Server VM (compilación 12 + 33, modo mixto, uso compartido)
  • Opciones de VM: -XX:+UseG1GC -server -Xmx1024m -Xms1024m

  • CPU: 8 núcleos

Resultados de rendimiento de JMH :

  • Calentamiento: 10 iteraciones, 1 s cada una.
  • Medida: 10 iteraciones, 1 s cada una.
  • Hilos: 1 hilo, sincronizará iteraciones
  • Unidades: ops / s

Código

Corriente + filtro complejo

public void complexFilter(ExecutionPlan plan, Blackhole blackhole) { long count = plan.getDoubles() .stream() .filter(d -> d < Math.PI && d > Math.E && d != 3 && d != 2) .count(); blackhole.consume(count); }

Corriente + filtros múltiples

public void multipleFilters(ExecutionPlan plan, Blackhole blackhole) { long count = plan.getDoubles() .stream() .filter(d -> d > Math.PI) .filter(d -> d < Math.E) .filter(d -> d != 3) .filter(d -> d != 2) .count(); blackhole.consume(count); }

Corriente paralela + filtro complejo

public void complexFilterParallel(ExecutionPlan plan, Blackhole blackhole) { long count = plan.getDoubles() .stream() .parallel() .filter(d -> d < Math.PI && d > Math.E && d != 3 && d != 2) .count(); blackhole.consume(count); }

Secuencia paralela + filtros múltiples

public void multipleFiltersParallel(ExecutionPlan plan, Blackhole blackhole) { long count = plan.getDoubles() .stream() .parallel() .filter(d -> d > Math.PI) .filter(d -> d < Math.E) .filter(d -> d != 3) .filter(d -> d != 2) .count(); blackhole.consume(count); }

Antigua moda java iteración

public void oldFashionFilters(ExecutionPlan plan, Blackhole blackhole) { long count = 0; for (int i = 0; i < plan.getDoubles().size(); i++) { if (plan.getDoubles().get(i) > Math.PI && plan.getDoubles().get(i) > Math.E && plan.getDoubles().get(i) != 3 && plan.getDoubles().get(i) != 2) { count = count + 1; } } blackhole.consume(count); }

Puedes intentarlo ejecutando el comando docker:

Para Java 8:

ventana acoplable ejecutar -it volkodav / java-filter-benchmark: java8

Para Java 12:

ventana acoplable ejecutada -it volkodav / java-filter-benchmark: java12

Código fuente:

https://github.com/volkodavs/javafilters-benchmarks