Por qué es el Sistema.arraycopy nativo en Java?


Me sorprendió ver en la fuente Java ese Sistema.arraycopy es un método nativo.

Por supuesto, la razón es porque es más rápido. Pero ¿qué trucos nativos es el código capaz de emplear que lo hacen más rápido?

¿Por qué no simplemente hacer un bucle sobre la matriz original y copiar cada puntero a la nueva matriz - seguramente esto no es tan lento y engorroso?

Author: polygenelubricants, 2010-05-05

5 answers

En código nativo, se puede hacer con un solo memcpy / memmove, a diferencia de n operaciones de copia distintas. La diferencia en el rendimiento es sustancial.

 73
Author: Péter Török,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-31 22:25:40

No se puede escribir en Java. El código nativo es capaz de ignorar o eludir la diferencia entre matrices de Objetos y matrices de primitivas. Java no puede hacer eso, al menos no de manera eficiente.

Y no se puede escribir con un solo memcpy(), debido a la semántica requerida por los arrays superpuestos.

 15
Author: user207421,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-15 06:56:46

Es, por supuesto, dependiente de la implementación.

HotSpot lo tratará como un "intrínseco" e insertará código en el sitio de la llamada. Es código máquina, no código C lento. Esto también significa que los problemas con la firma del método desaparecen en gran medida.

Un bucle de copia simple es lo suficientemente simple como para que se le puedan aplicar optimizaciones obvias. Por ejemplo, desenrolle en bucle. Exactamente lo que sucede es otra vez dependiente de la implementación.

 9
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-05 10:17:22

En mi propio Sistema de pruebas.arraycopy() para copiar matrices de múltiples dimensiones es de 10 a 20 veces más rápido que interleaving for loops:

float[][] foo = mLoadMillionsOfPoints(); // result is a float[1200000][9]
float[][] fooCpy = new float[foo.length][foo[0].length];
long lTime = System.currentTimeMillis();
System.arraycopy(foo, 0, fooCpy, 0, foo.length);
System.out.println("native duration: " + (System.currentTimeMillis() - lTime) + " ms");
lTime = System.currentTimeMillis();

for (int i = 0; i < foo.length; i++)
{
    for (int j = 0; j < foo[0].length; j++)
    {
        fooCpy[i][j] = foo[i][j];
    }
}
System.out.println("System.arraycopy() duration: " + (System.currentTimeMillis() - lTime) + " ms");
for (int i = 0; i < foo.length; i++)
{
    for (int j = 0; j < foo[0].length; j++)
    {
        if (fooCpy[i][j] != foo[i][j])
        {
            System.err.println("ERROR at " + i + ", " + j);
        }
    }
}

Esto imprime:

System.arraycopy() duration: 1 ms
loop duration: 16 ms
 4
Author: jumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-28 14:44:54

Hay algunas razones:

  1. Es poco probable que el JIT genere código de bajo nivel tan eficiente como un código C escrito manualmente. El uso de low level C puede habilitar muchas optimizaciones que son casi imposibles de hacer para un compilador JIT genérico.

    Vea este enlace para algunos trucos y comparaciones de velocidad de implementaciones C escritas a mano (memcpy, pero el principio es el mismo): Verifique esto La optimización de Memcpy mejora la velocidad

  2. La versión C es bonita mucho independiente del tipo y tamaño de los miembros de la matriz. No es posible hacer lo mismo en java ya que no hay manera de obtener el contenido de la matriz como un bloque de memoria raw (por ejemplo. puntero).

 3
Author: Hrvoje Prgeša,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-28 14:06:17