Porque é que a atribuição de uma única matriz 2D tomada mais do que um ciclo de atribuição de múltiplos arranjos 1D do mesmo tamanho total e forma?

user10339780:

Eu pensei que seria mais rápido para criar diretamente, mas na verdade, a adição de laços leva apenas metade do tempo. O que aconteceu que abrandou tanto?

Aqui está o código de teste

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class Test_newArray {
    private static int num = 10000;
    private static int length = 10;

    @Benchmark
    public static int[][] newArray() {
        return new int[num][length];
    }

    @Benchmark
    public static int[][] newArray2() {
        int[][] temps = new int[num][];
        for (int i = 0; i < temps.length; i++) {
            temps[i] = new int[length];
        }
        return temps;
    }

}

Os resultados do teste são como se segue.

Benchmark                Mode  Cnt    Score   Error  Units
Test_newArray.newArray   avgt   25  289.254 ± 4.982  us/op
Test_newArray.newArray2  avgt   25  114.364 ± 1.446  us/op

O ambiente de teste é como se segue

versão JMH: 1,21

VM versão: JDK 1.8.0_212, OpenJDK 64-Bit Servidor VM, 25.212-b04

apangin:

Em Java há uma instrução bytecode separado para alocação de arrays multidimensionais - multianewarray.

  • newArrayUtilizações de referência multianewarraybytecode;
  • newArray2invoca simples newarrayno circuito.

O problema é que HotSpot JVM tem nenhum caminho rápido * para multianewarraybytecode. Esta instrução é sempre executada na VM de tempo de execução. Portanto, a alocação não está embutido no código compilado.

A primeira referência tem de penalidade de desempenho de pagamento de alternar entre contextos Java e VM de tempo de execução. Além disso, o código de atribuição comum no tempo de execução de VM (escrita em C ++) não é tão optimizado quanto atribuição indexados num código compilado-JIT, apenas porque é genérico , ou seja, não optimizada para o tipo de objecto específico ou para o local de chamada especial, realiza verificações de tempo de execução adicionais, etc.

Aqui estão os resultados de profiling ambos os benchmarks com async-profiler . Eu costumava JDK 11.0.4, mas para JDK 8 o quadro é semelhante.

newArray

newArray2

No primeiro caso, 99% do tempo gasto no interior OptoRuntime::multianewarray2_C- o código C ++ no tempo de execução VM.

No segundo caso, a maior parte do gráfico é verde, o que significa que o programa é executado principalmente no contexto de Java, na verdade, a execução do código compilado-JIT optimizado especificamente para o referencial dado.

EDITAR

* Só para esclarecer: em HotSpot multianewarraynão é otimizado muito bem por design. É bastante caro para implementar uma operação tão complexa em ambos os compiladores JIT corretamente, enquanto os benefícios de tal otimização seria questionável: alocação de matrizes multidimensional raramente é um gargalo de desempenho em uma aplicação típica.

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=311784&siteId=1
Recomendado
Clasificación