java: comparación del rendimiento de la concatenación de cinco cadenas utilizando el marco de evaluación comparativa jmh

java: comparación del rendimiento de la concatenación de cinco cadenas utilizando el marco de evaluación comparativa jmh

introducción

Java proporciona 5 métodos de concatenación de cadenas y usar + para concatenar cadenas es el método más común. Además, existen StringBuilder, StringBuffer, MessageFormat y StringFormat

para comparar el rendimiento de los siguientes cinco métodos simplemente desde el tiempo de ejecución del empalme.

Comparando resultados

Primero observe los resultados de la ejecución, donde la puntuación es el tiempo de ejecución (sutil) y el error puede considerarse un error.

El tiempo de ejecución de corto a largo es: + < StringBuilder < StringBuilder < MessageFormat < StringFormat

Benchmark                  Mode  Cnt     Score     Error  Units
JmhTest.testMessageFormat  avgt    5   722.346 ± 134.540  us/op
JmhTest.testStringBase     avgt    5     6.905 ±   2.604  us/op
JmhTest.testStringBuffer   avgt    5     8.291 ±   5.311  us/op
JmhTest.testStringBuilder  avgt    5     7.192 ±   3.861  us/op
JmhTest.testStringFormat   avgt    5  1273.906 ±  69.336  us/op

punto de referencia jmh

agregar dependencias

<!--基准测试-->
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.35</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.35</version>
</dependency>

Notas JMH

@BenchMarkMode Establece el modo de prueba comparativa [método o clase]

@OutPutTimeUnit La unidad de tiempo predeterminada para informar resultados [clase, método]

@Warmup calentamiento, establece parámetros de configuración específicos como tiempos, tiempo, etc.

@Measurement es similar al calentamiento, pero la configuración es @Fork cuando se mide

la prueba general varias veces

@State establece el alcance de los objetos de configuración, define el grado de intercambio entre subprocesos

@Setup función de configuración de subprocesos antes de la ejecución, inicialización

@TearDown operaciones de procesamiento posteriores a la prueba 【Método】

@BenchMark marca prueba de referencia 【Método]

@OperationsPerInvocation realiza una comunicación de operaciones múltiples con la referencia y ejecuta el ajuste JMH

  • @BenchMarkMode
    establece el modo de ejecución de la prueba comparativa. Puede elegir ponerlo en el método y solo tendrá efecto para el método.

    Mode.Throughput: Modo de rendimiento, obtenga el número de operaciones por unidad de tiempo, ejecute el método @BenchMark continuamente y calcule el rendimiento total de todos los subprocesos de trabajo.

    Mode.AverageTime: modo de tiempo promedio, obtiene el tiempo promedio de cada operación y calcula el tiempo promedio de todos los subprocesos de trabajo.

    Mode.SimpleTime: modo de muestreo de tiempo, que muestrea el tiempo de cada función de operación, ejecuta funciones @BenchMark continuamente y extrae aleatoriamente el tiempo requerido para la operación.

    Mode.SingleShotTime: modo de disparo único, pruebe el tiempo de una sola operación, ejecute la función @BenchMark continuamente, ejecútela solo una vez y calcule el tiempo: este modo solo ejecuta la función @BenchMark una vez, por lo que necesita calentarse, si el valor de referencia es pequeño, utilice el muestreo de patrón SimpleTime.

    Mode.All: sin modo, usa todos los modos básicos, el mejor efecto.

escribir código de prueba

Ejecute el método principal para iniciar la prueba y espere pacientemente a que se complete.

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.text.MessageFormat;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime) //基准测试的默认模式
@OutputTimeUnit(TimeUnit.MICROSECONDS) //时间单位:纳秒、微妙、毫秒、秒、分、时
@State(Scope.Thread)
@Fork(1) //进程数一般设置为1
//@Threads(1) //线程数
@Warmup(iterations = 2,time = 2) //预热迭代次数,time控制每次迭代的间隔时间(默认秒)
@Measurement(iterations = 5,time = 2) //测量迭代次数,time控制每次迭代的间隔时间(默认秒)
public class JmhTest {
    private int _loop = 1000;
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder().include(JmhTest.class.getSimpleName()).build();
        new Runner(opt).run();
    }
    //StringBuffer
    @Benchmark //被测试的方法
    public void testStringBuffer() {
        for(int i = 0; i< _loop; i++){
            StringBuffer sbr = new StringBuffer();
            String s = sbr.append("1111").append(",")
                    .append("2222").append(",")
                    .append("3333").append(",")
                    .append("4444").toString();
        }
    }
    //StringBuilder
    @Benchmark //被测试的方法
    public void testStringBuilder() {
        for(int i = 0; i< _loop; i++){
            StringBuilder sbr = new StringBuilder();
            String s = sbr.append("1111").append(",")
                    .append("2222").append(",")
                    .append("3333").append(",")
                    .append("4444").toString();
        }
    }
    //MessageFormat
    @Benchmark
    public void testMessageFormat() {
        for(int i = 0; i< _loop; i++){
            String s = MessageFormat.format("{0},{1},{2},{3}","1111","2222","3333","4444");
        }
    }
    //String.format
    @Benchmark
    public void testStringFormat() {
        for(int i = 0; i< _loop; i++){
            String s = String.format("%s,%s,%s,%s","1111","2222","3333","4444");
        }
    }
    //字符串拼接
    @Benchmark
    public void testStringBase() {
        for(int i = 0; i< _loop; i++){
            String s = "1111";
            s+=",2222";
            s+=",3333";
            s+=",4444";
        }
    }

}

Descripción de los resultados de la prueba.

Lo anterior realmente compara 5 funciones. La configuración de la prueba es que cada función se calienta y ejecuta una vez, y se cuenta el tiempo promedio de ejecución de las siguientes 5 veces.

True para usar la prueba del modo Mode.AverageTime, la salida después de ejecutar cada función es:

Result "com.cnpc.epai.researchdata.data.service.JmhTest.testStringFormat":
  1254.609 ±(99.9%) 174.543 us/op [Average]
  (min, avg, max) = (1174.821, 1254.609, 1282.413), stdev = 45.328
  CI (99.9%): [1080.066, 1429.151] (assumes normal distribution)

El resultado final de la ejecución es:

Benchmark                  Mode  Cnt     Score     Error  Units
JmhTest.testMessageFormat  avgt    5   722.346 ± 134.540  us/op
JmhTest.testStringBase     avgt    5     6.905 ±   2.604  us/op
JmhTest.testStringBuffer   avgt    5     8.291 ±   5.311  us/op
JmhTest.testStringBuilder  avgt    5     7.192 ±   3.861  us/op
JmhTest.testStringFormat   avgt    5  1273.906 ±  69.336  us/op

Donde Score es el tiempo de ejecución (sutil) y Error es el error;

en conclusión:

1. La forma de utilizar StringBuilder es la más eficiente.
2. Si no realiza el empalme de cadenas en el cuerpo del bucle, simplemente use + directamente.
3. Si el empalme de cadenas se realiza en un escenario concurrente, se debe utilizar StringBuffer en lugar de StringBuilder.

Supongo que te gusta

Origin blog.csdn.net/xxj_jing/article/details/129680765
Recomendado
Clasificación