Alfabetización! Java matrices de longitud variable, en este aspecto a la derecha!

De: ImportNew / Qinyou Hua | Editor: Lele
enlace: tutorials.jenkov.com/java-performance/resizable-array.html

A veces esperamos que guardar los datos en una sola matriz continua, con el fin de acceder fácil y rápidamente los datos, pero necesidad de ajustar el tamaño de la matriz o de su prolongación. matrices de Java no puede cambiar el tamaño, sólo la matriz no es suficiente para lograr sus objetivos. matrices de longitud variable de los tipos primitivos necesita su propia aplicación. Este artículo le mostrará cómo implementar Java matrices de longitud variable.

¿Por qué no ArrayList?

Para satisfacer las necesidades de principio del artículo, ¿por qué no utilizar Java ArrayList? Si no se cumple una de las siguientes condiciones, puede utilizar ArrayList:

  • Un tipo de objeto almacenado en la matriz;

  • En el tipo original almacenado en la matriz, no hay requisitos de rendimiento o de memoria particulares.

clase Java ArrayList sólo se aplica a los objetos, no para los tipos primitivos (int, byte, largas, etc.). tipos de datos en bruto de tienda Uso ArrayList, embalaje automáticamente el objeto en el ArrayList inserción, se convertirán en el tipo de original cuando se descomprimen los mismos eliminado. Embalaje y desembalaje en el momento de los elementos de inserción y elementos de acceso traerá una sobrecarga adicional cuando se trata de optimizar el rendimiento, se debe evitar estos costos (Este artículo es parte del seguimiento del rendimiento de Java).

Además, este método no puede determinar la posición del objeto envasado automático se almacena en la memoria. Se puede estar dispersa en varios lugares almacenados en el montón. Por lo tanto, el tipo original de la matriz a ser mucho más lento en comparación con la velocidad de acceso, el antiguo almacenado de forma contigua en la memoria.

Además, el tipo original de embalaje traerá sobrecarga de memoria adicional, como objetos de gran longitud se guardarán en largo.

fuente del artículo

La implementación de este matrices de longitud variable código fuente de Java se puede descargar desde GitHub: github.com/jjenkov/java-resizable-array

Código contiene tres clases de Java y dos unidades de prueba.

Ejemplo con matrices de longitud variable

Se supone que un servidor recibe un mensaje diferente tamaños. Algunos de los correos es muy pequeño (menos de 4 KB), otros grandes (1 MB o más).

Si el servidor está conectado para recibir mensajes desde una pluralidad de (más de 100.000), la necesidad de limitar la memoria pre-asignado para cada mensaje. Cada memoria intermedia puede no sólo en el valor máximo (1 MB o 16 MB) para asignar memoria. Al aumentar el número de conexiones y mensajes, este enfoque se ejecutará rápidamente de la memoria del servidor! 100_000 x 1 MB = 100 GB (esto es una estimación, para ayudar a entender el problema).

La mayoría asume que el mensaje es relativamente pequeño, al principio se puede utilizar un búfer más pequeño. Si el mensaje excede el tamaño de la memoria caché, la asignación de una nueva matriz más grande, y copia los datos en la matriz. Si el mensaje excede la nueva matriz asignado, y luego asignar un conjunto más amplio que antes, y para copiar el mensaje a la matriz.

Con esta estrategia, la mayoría de los mensajes se almacenan por lo general sólo una pequeña matriz. Esto significa que la memoria del servidor se ha utilizado de manera más eficiente. 100_000 x 4 KB (buffer pequeño) = 400 MB más servidor debe ser capaz de manejar adecuadamente. Incluso 4GB (1_000_000 x 4 KB), el servidor ahora puede cumplir con los requisitos.

diseño matrices de longitud variable

La matriz de longitud variable contiene dos componentes:

  • ResizableArray

  • ResizableArrayBuffer

ResizableArrayBuffer contiene una gran matriz. La matriz se divide en tres partes. Como una pequeña sección de la matriz, la matriz se utiliza como un período, un periodo utilizado como una gran matriz. clase ResizableArray representa una matriz de longitud variable, los datos subyacentes se almacenan en ResizableArrayBuffer.

La siguiente figura muestra la matriz divide en tres secciones, cada una subdividirse en trozos pequeños.

Por pequeño, mediano, grande espacio reservado para los diferentes tipos de datos, ResizableArrayBuffer no puede ser llenado para asegurar un cierto tamaño de los datos. Por ejemplo, los datos pequeños no ocupará toda la matriz de memoria, bloqueando de este modo el almacenamiento de datos de tamaño medio y grande. Del mismo modo, los datos recibidos no ocuparán toda la memoria grande, bloqueando de esta manera los datos de almacenamiento de datos pequeñas y medianas empresas.

A medida que el almacenamiento de datos subyacente empezar poco a poco, si el espacio de almacenamiento de pequeño arsenal se agota, independientemente de si existe una matriz de matrices o gran espacio, no se puede asignar una nueva matriz. Permite que el pequeño lo suficientemente grande como matriz para reducir la probabilidad de que esto ocurra.

Incluso pequeña gama se ha agotado, todavía se puede poner una pequeña de datos se convierten en datos de medianas y grandes.

optimización

Una optimización: con sólo un bloque de memoria. Nuevo bloque se asigna según sea necesario para extenderse directamente detrás del bloque. Esto elimina la necesidad de copiar datos de la antigua a la nueva matriz la matriz puede ser directamente "extendida" bloque de expansión a un segundo bloque de memoria acomodar nuevos datos y los datos antiguos, que está escrito añadir directamente nuevos datos. Esto evita el caso en que la copia de todas las matrices de datos.

Desventaja de la optimización anterior es que si el siguiente bloque de memoria no se puede ampliar todavía tienen que copiar datos. Por lo tanto tenga que añadir "escalable" comprobar esta pequeña sobrecarga operativa. Además, si el tamaño de bloque de memoria es demasiado pequeño, los datos en el caso de datos de gran tamaño presentes en expansión de datos pequeña, mediana y se produce con frecuencia.

el seguimiento de bloques libres

Una gran variedad de ResizableArrayBuffer interna igualmente dividido en tres secciones. Cada segmento se divide en bloques más pequeños de memoria; el mismo tamaño de bloque de memoria en cada segmento; la misma matriz de almacenamiento de pequeño tamaño de bloque; los mismos bloques de memoria de tamaño medio de la matriz, el mismo tamaño de bloque de matriz de gran capacidad de memoria.

Cada segmento en el mismo tamaño de bloque de memoria hace que sea más fácil de realizar el seguimiento del estado de uso de bloques. Cola puede ser índice de inicio de grabación utilizado para cada bloque. También se requiere una matriz registro de cola compartida en cada segmento. Por último, una cola para realizar un seguimiento de los pequeños bloques libres de datos, una cola de bloques de datos vacíos medio de grabación, una cola está inactivo por grandes bloques de datos.

El tipo de datos adquiridos a partir de la respuesta cola el siguiente índice de bloque de partida libre, el bloque de memoria asignada puede ser implementado a partir de cualquiera de los segmentos de datos. El índice de inicio puede ser liberado de nuevo en el bloque de datos de cola correspondiente.

Aquí, he utilizado un simple cola de memoria cíclica. GitHub repositorio de código QueueIntFlip correspondiente. Aro de tope Tutorial: tutorials.jenkov.com/java-performance/ring-buffer.html

la escritura extendida

Al escribir datos en una matriz, matrices de longitud variable se expanden automáticamente. Si los intentos actuales de exceden el espacio de almacenamiento asignado a la matriz de datos de escritura, la asignación de un nuevo y más grande bloque de copia de la memoria de todos los datos a un nuevo bloque y luego puesto en libertad antes de que los pequeños bloques de memoria.

matriz de liberación

Una vez que la gama completa de longitud variable de cambio de tamaño, debe ser liberada de forma que puede recibir otros mensajes.

使用 ResizableArrayBuffer

A continuación se muestra cómo se utilizan en GitHub ResizableArrayBuffer.

Crear un ResizableArrayBuffer

En primer lugar, se debe crear un ResizableArrayBuffer. Ejemplos son los siguientes:

int smallBlockSize  =    4 * 1024;  
int mediumBlockSize =  128 * 1024;  
int largeBlockSize  = 1024 * 1024;  

int smallBlockCount  = 1024;  
int mediumBlockCount =   32;  
int largeBlockCount  =    4;  

ResizableArrayBuffer arrayBuffer =  
        new ResizableArrayBuffer(  
                smallBlockSize , smallBlockCount,  
                mediumBlockSize, mediumBlockCount,  
                largeBlockSize,  largeBlockCount);

Este ejemplo crea un ResizableArrayBuffer contiene una pequeña matriz de 4 KB, la matriz de 128KB y 1 MB grandes matrices. ResizableArrayBuffer pequeña matriz de memoria 1024 que comprende (co 4MB), el tamaño de la matriz compartida 32 en la matriz (un total de 4 MB) y cuatro arrays grandes (co 4MB), un 12 MB total de completa.

Ejemplos de obtención ResizableArray

Para obtener ejemplo ResizableArray, el método de llamada ResizableArrayBuffer getArray () como sigue:

ResizableArray resizableArray = arrayBuffer.getArray();

Aquí obtener un mínimo ResizableArray (antes de 4 KB).

datos de escritura a ResizableArray

Llamado a la escritura método de escritura de datos en la ResizableArray (). En ResizableArray clase GitHub contiene sólo un método de escritura (), que es un parámetro ByteBuffer. Sin embargo, se puede añadir más de escritura () métodos de acuerdo a sus propias necesidades.

Aquí está un ejemplo de datos de escritura:

public byte[] sharedArray = null;  
public int    offset      = 0;  
public int    capacity    = 0;  
public int    length      = 0;

El código anterior para copiar el contenido ResizableArray ByteBuffer matriz. Write () devuelve el número de bytes copiados de ByteBuffer.

Si los datos contienen ByteBuffer allá de la capacidad ResizableArray, entonces ResizableArray tratará de ampliar, los datos de la ByteBuffer para hacer espacio. Incluso si se extiende al máximo ResizableArray no puede acomodar todos los datos ByteBuffer, las Write () devuelve el método -1, y no copiar cualquier dato!

Leer datos de ResizableArray

Cuando los datos de lectura de ResizableArray se pueden leer directamente desde todas las instancias directamente ResizableArray compartida matriz. ResizableArray contiene los siguientes campos públicos:

public byte[] sharedArray = null;  
public int    offset      = 0;  
public int    capacity    = 0;  
public int    length      = 0;
  • sharedArray corresponde campo ResizableArray todas las instancias de array, es decir, la matriz interna ResizableArrayBuffer compartidos.

  • desplazamiento corresponde al índice de campo a partir de la matriz compartida, los datos guardados ResizableArray aquí.

  • capacidad asignada al campo de tamaño de bloque contiene instancia ResizableArray.

  • El campo de longitud contiene el número de bloques utilizado realmente ResizableArray.

Para leer los datos escritos ResizableArray largo como leídos desde sharedArray [desplazamiento] a sharedArray [compensar + longitud -1] a byte.

释放 ResizableArray

Una vez ResizableArray instancia tiene que ser liberada después de su uso. Mientras la llamada de método ResizableArray free () puede ser como sigue:

resizableArray.free();

Si los bloques asignados a la ResizableArray tamaño de bloque de cómo llamar a free () puede utilizarse para devolver la cola correcta.

transformar Diseño

Puede modificar ResizableArrayBuffer diseñado de acuerdo a sus necesidades. Por ejemplo, lo que puede crear más de tres segmentos de datos. También debe ser muy fácil de operar, siempre y cuando la mirada GitHub para modificar el código fuente.

Publicado 50 artículos originales · ganado elogios 1706 · Vistas 2,22 millones +

Supongo que te gusta

Origin blog.csdn.net/zl1zl2zl3/article/details/105327016
Recomendado
Clasificación