Apoyo Comprimido Cadenas que se Cayó en la JVM HotSpot?

En esta página de Oracle Java HotSpot VM Opciones, enumera -XX:+UseCompressedStrings como disponible y activada por defecto. Sin embargo, en Java 6 update 29, que está desactivada por defecto y en Java 7 update 2 muestra una advertencia

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option UseCompressedStrings; support was removed in 7.0

¿Alguien sabe el pensamiento detrás de la eliminación de esta opción?


clasificación de las líneas de un enorme file.txt en java

Con -mx2g, en este ejemplo se tomó 4.541 segundos con la opción de 5.206 segundo con apagado en Java 6 update 29. Es difícil ver que influye en el rendimiento.

Nota: Java 7 update 2 requiere 2.0 G, mientras que Java 6 update 29 comprimido sin cadenas requiere de 1.8 GB y con comprimidos de cadena requiere sólo 1.0 GB.

  • no relacionadas con exactitud, pero para el futuro ref: -XX:+PrintFlagsFinal listas de todos los indicadores disponibles y sus valores.
  • Mirando hacia adelante a esta característica haciendo una reaparición en SIIII 254 en JDK 9. Todavía guardo JDK6-32 alrededor de una pequeña pero de la cadena pesada de la aplicación (100MB de RAM total, frente a los 150 mb en JDK8-32, vs 250 MB o JDK8-64) y un 30% más rápido reg-ex búsquedas.
InformationsquelleAutor Peter Lawrey | 2012-01-12

5 Kommentare

  1. 41

    Originalmente, esta opción se agregó a mejorar SPECjBB rendimiento. Las ganancias se debe a la reducción de la memoria requisitos de ancho de banda entre el procesador y la memoria DRAM. Carga y almacenamiento de los bytes en el byte[] consume 1/2 del ancho de banda frente a los caracteres en el char[].

    Sin embargo, esto tiene un precio. El código tiene que determinar si la matriz interna es un byte[] o char[]. Esto toma tiempo de la CPU y si la carga de trabajo no es la memoria ancho de banda restringida, puede provocar que el rendimiento de la regresión. También hay un código de mantenimiento de los precios debido a la mayor complejidad.

    Porque no había suficiente producción-como las cargas de trabajo que mostraron aumentos significativos (excepto, quizás, SPECjBB), la opción fue eliminado.

    Hay otro ángulo de este. La opción reduce el uso del montón. Aplicables de Cadenas, se reduce el uso de memoria de las Cadenas por 1/2. Este ángulo no fue considerada en el momento de la opción de eliminación. Para cargas de trabajo que son la memoria capacidad restringido (es decir, tienen que correr con limitado espacio de montón de GC y lleva un montón de tiempo), esta opción puede resultar útil.

    Si hay suficiente memoria capacidad restringida de la producción-como las cargas de trabajo se pueden encontrar para justificar la inclusión, a continuación, tal vez la opción va a ser traído de vuelta.

    Editar 3/20/2013: Una media server montón de volcado utiliza el 25% del espacio de las Cadenas. La mayoría de las Cadenas son compresibles. Si la opción es reintroducido, se podría ahorrar la mitad de este espacio (por ejemplo, ~12%)!

    Editar 3/10/2016: Una característica similar a la compresión de las cadenas está volviendo en JDK 9 SIIII 254.

    • Supongo que los grandes JEE sistemas basados va a almacenar la mayoría de sus datos en una base de datos, JSE sistemas de ello, pero en menor grado. Ser capaz de almacenar datos en la memoria reduce el tamaño de la memoria caché se puede tener, pero es menos crítico (es decir, usted no conseguirá un fracaso como tal) estoy suponiendo que el SPECjBB no toma en cuenta el costo de ser capaz de caché menos datos. Para mis aplicaciones, me tienda la mayor parte de mis datos en los Archivos Asignados en Memoria con byte basado en la codificación de las cadenas y el uso de re-utilizable StringBuilder en lugar de Cadena para limitar GC impacto, por lo que es posible que no me ayude tanto como lo hizo.
    • No debería tener precio. Java debe ser capaz de proporcionar una api que podría ser utilizado para construir una cadena a partir de una fuente que se sabe que sólo contienen bytes. En su lugar se elige a la desconfianza en el programador y verificar que todo en sí mismo. Del mismo modo, java podría proporcionar una api que permite que una Cadena se crea una instancia de una matriz existente; en lugar de ello completamente desconfía de todos los programadores y las fuerzas de siempre copia de la matriz.
    • Espero que esto se agrega de nuevo. Realmente es muy útil para acelerar el análisis de texto de aplicaciones que manejan un mínimo de conjuntos de caracteres y, definitivamente, se reduce el uso del montón si usted está manteniendo su conjunto de datos en la memoria.
    • Estoy bastante seguro de que lo que usted describe socavaría la JVM de la seguridad/ de la Aceptación de su matriz como un componente de Cadena hace que la Cadena mutable y con la Cadena que se utiliza como nombres de clase que probablemente podría hacer lo que quieras en la JVM. De modo que el no-copia constructor público String(char[]) tendría que ser custodiado por un SecurityManager, lo que probablemente hacen más lento que la copia de la versión.
    • No es un problema si podemos hacer inmutable matrices. Por el camino, van a escapar de análisis de optimizar la distancia de la copia?
    • Pero, ¿cómo podemos hacer inmutable matrices? Me temo, que escapar de análisis es mucho más débil de lo que podría ser y dudo, que trabaja con matrices. Pero yo podría estar completamente equivocado. Para evitar la copia, sería necesario determinar que la char[] obtiene sin usar y utilizar esta información en la cadena de constructor. Esto suena un poco complicado y no es probablemente lo suficientemente comunes (más a menudo, se utiliza una StringBuilder, donde se podría aplicar, pero el asignado matriz rara vez es del tamaño exacto).
    • Un divertido relacionados con la función de regresar de la matriz interna de String.toCharArray, siempre que se pueda demostrar, que no recibe modificado.
    • Cómo se comprimen las cadenas beneficiado?
    • Oigo a algún lugar que escapar de análisis puede hacer de la matriz asignado en la pila (si es menos de 64 bytes) así que quizá no es tanto un problema. SIIII 169 de la oit tiene algo sobre inmutable de la matriz.
    • Comprimido cadenas de guardar en caso de LATIN-1 la mitad de la matriz. Hay un montón de leer si quieres: bugs.openjdk.java.net/browse/JDK-8054307. Solo sé un poco acerca de escapar de análisis. SIIII 169 es genial, pero puede tomar un montón de tiempo hasta que se implemente.

  2. 14

    Solo para añadir, para los interesados…

    La java.lang.CharSequence interfaz (que java.lang.String implementa), permite la más compacta de las representaciones de las Cadenas de caracteres de UTF-16.

    Aplicaciones que manipular una gran cantidad de cadenas, probablemente debería estar escrito a aceptar CharSequence, que se iba a trabajar con java.lang.String, o más compacto representaciones.

    De 8 bits (UTF-8), o incluso 5, 6, o 7 bits codificados, o incluso comprimir las cadenas pueden ser representados como CharSequence.

    CharSequences también pueden ser mucho más eficientes para manipular – subsecuencias puede ser definido como las vistas (punteros) en el contenido original, por ejemplo, en lugar de copiar.

    Por ejemplo en concurrente árboles, un sufijo árbol de diez obras de Shakespeare, requiere 2 gb de RAM utilizando CharSequencebasado en nodos, y requeriría 249GB de RAM si usar char[] o de Cadena de nodos.

    • CharSequence parece interesante, pero veo que no hay medio por el cual una aplicación puede indicar si debe ser considerado inmutable (es decir, si la persistencia de una referencia es suficiente para conservar la secuencia de caracteres en el mismo). Obviamente, es posible para cualquier interfaz para ser implementado en la quebrada de la moda, pero la interfaz parece más útil si se había IsImmutable y AsImmutable métodos.
    • Sí la inmutabilidad de un CharSequence depende de la inmutabilidad de todos los CharSequences referencias transitivamente. Supongo que en el caso de implementar un ImmutableCharSequence que sólo puede hacer referencia a otros ImmutableCharSequences, entonces se podría hacer instanceof cheques, para detectar la inmutabilidad transitivamente.
    • Aunque sería útil tener una interfaz ImmutableCharSequence de la que heredó CharSequence pero no añade nuevos miembros-sólo una expectativa de que IsImmutable volvería true y AsImmutable volvería this, y los métodos que necesitan inmutable cadenas de caracteres podría aceptar ese tipo sin tener que llamar a IsImmutable o AsImmutable, no hay manera de que uno puede restringir lo que los tipos de objetos que podrían ser encapsulado por un ImmutableCharSequence, ya que lo que sería cuestión no es si cualquier encapsulado instancia de un tipo mutable, sino más bien de si iba a ser nunca…
    • …expuestos a cualquier cosa que pudiera mutar ella. La gran mayoría de los objetos inmutables encapsular las instancias de mutable clases, ya sea directa o indirectamente, pero son inmutables a pesar de que debido a que esos casos son nunca libremente expuesta al mundo exterior.
  3. 13

    Ya que no había votos, creo que no me falta algo evidente por lo que han iniciado sesión como un bug (al menos una omisión en la documentación)

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7129417

    (Debe ser visible en un par de días)

    • presentación el error fue la cosa correcta a hacer, sin embargo, en general de MANERA que no se conoce ningún JVM ingenieros de los participantes.
    • cierto, pero LO es mucho más sensible. 😉 Quería comprobar que no me falta algo obvio. @Nathan explicación es tan bueno como cualquier otro.
    • mi opinión sobre la historia sería: compilación JIT de la Cadena de métodos intenta utilizar ESS asamblea, pero que iba a ser más duro para generar código de forma adecuada w/ ambos char[] y byte[]. No es imposible, pero bastante duro y se cayó por el apoyo.
    • como para ser sensible, JSR-166 lista de correo suele ser bastante sensible, pero esa característica sería difícil relacionarse con JSR-166.
    • Me pregunto ¿qué dificultades habría sido con el hecho de tener, en lugar de tener un tipo de matriz para cada numérico primitivo, tener una plataforma unificada primitivo-matriz de tipo de instancia que podría ser lanzado a cualquier otro, junto con una JVM-define static final de la variable que indica si estas matrices se comportan como big-endian o little-endian? Hay muchos tipos de operación que podría ser acelerado por el acaparamiento de dos o cuatro cosas a la vez.
    • usted no necesita atómica de acceso a cada elemento de la matriz, a continuación, usted tiene la JNI (probablemente factible así). En realidad hay cosas similares (el que se describa) en forma Directa ByteBuffers (esp con los no-alineados soporte de CPU), se puede tratar a cada ByteBuffer como cualquier otro tipo primitivo. El principal problema es que la longitud (o límite en el caso de ByteBuffers) no es constante, por lo tanto el compilador tendría mucho más difícil de optimizar.
    • Java es utilizado en el mundo real de las plataformas donde sería más difícil para el CPU atómicamente escribir un solo byte dentro de un int[] de un único byte dentro de un byte[]? Puedo imaginar un sistema embebido, donde sólo una parte de la memoria permitida escribe del individuo que escribe, pero no puedo imaginar una JVM de la implementación de la asignación de byte[] instancias en que parte del espacio de la memoria y int[] instancias en otros lugares.
    • Era más acerca de la escritura no alineados int/largo en un » byte[]’, si sólo necesita int[].asByteArrayView() que no será un gran problema (como ByteBuffers ahora) También new byte[5] no puede ser representada como int[] o char [], la memoria tiene que ser asignada y collar y comportamiento al llegar a la parte superior de los límites definidos. De cualquier manera, que no ayudará a la String caso en cuestión. La dificultad viene de la manipulación del contenido de la matriz byte[] o char[] de manera diferente, es posible la clonación de las rutas de código (por la JVM +ınsecos)
    • Las ventajas de rendimiento de los comprimidos cadenas mejoraría considerablemente si los métodos de proceso en trozos de más de un byte. Dado un long l que contiene 8 caracteres ASCII «little-endian», de código en un procesador de 64 bits podría añadir los caracteres en un valor de hash de acuerdo con el presente a través de l-=225*((l & 0xFF00FF00FF00FF00) >>> 8); l-=64575*((l & 0xFFFF0000FFFF0000) >>> 16); l-=4294043775*(l >>> 32); hash = (int)l - hash*1807454495; Uno long fetch, dos máscaras, y cuatro multiplica, en lugar de ocho bytes recupera y ocho multiplica.
    • La mayor de las ventajas de rendimiento de los comprimidos cadenas, la más probable es que esas ventajas sería para superar cualquier sobrecarga impuesta por tener que condicionalmente o prácticamente envío miembros. Si yo fuera el diseño de un String, probablemente tendría tres principales formatos de almacenamiento: una matriz de bytes para cadenas de caracteres ASCII, una matriz de caracteres no-ASCII cadenas, y una matriz de Object que se mantenga una lista de String un largo con una lista de las compensaciones (la concatenación de dos listas al estilo de las cadenas debe producir una nueva cadena con un combinado de lista cuyos elementos, excepto el primero y el último, fueron…
    • …entre 256 y 512 caracteres). Tener la lista de artículos que contienen referencias a String en lugar de la copia de matrices significa que si dos cuerdas se compararon y se encontró la igualdad, la referencia a la matriz almacenada en la más reciente podría ser reemplazado con que en el anterior, así agilizar futuras comparaciones.
    • Tenga en cuenta, no solo deja de JIT para optimizar el código generado y reducir la carga (aunque son muy baratos al golpear L1). Incluso ahora el JIT puede utilizar las características intrínsecas (y la ESS en x86 que es más eficaz que el de 64 bits de largo) para trabajar con la Cadena, simplemente no es visible en java nivel. Es cierto que no he sido el siguiente JIT por bastante tiempo, sin embargo. En realidad, como los de java1.7 hashCode usos primarios murmur32 como función hash y el original de la etiqueta no es muy utilizado. El código uses32 poco ops en todas partes y el JIT debe ser capaz de optimizar la recuperación también.
    • …Tener virtuales llamadas mataría rendimiento (no inline en la longitud (de), charAt() por lo tanto no se quita obligado cheques) a menos que las cuerdas son muy grandes y todo lo que puede estar contenida en la invoca métodos. Históricamente, String ha sido trasladado a la poseen solo un char[] y no offest, len; en los tiempos en que era posible compartir la char[] de StringBuffer, ser un punto de vista de otra cadena y más. Probablemente resultó todo ese código disminuido la mayoría de los casos de uso (y creado fugas).
    • …Todavía tengo new String(str) en algunas de las piezas a tratar con str pocos chars largo de la subcadena de varios KB. Es simplemente difícil de cubrir todo, y aún así ganar «Ese» punto de referencia tiene que seguir el juego con otra aplicación.
    • Yo creo que if (charData != null && index < charData.length) return charData[index] else return source.vCharAt(index); podría tarifa, así como la aplicación actual en el común de los casos. Almacén de cadenas cortas como char[] incondicionalmente, pero que utilizar algo más cuando la concatenación de cadenas grandes. Si source es final pero no charData, y tener «normal» cadenas conjunto source a this deben rendimiento adecuado de la memoria semántica (la primera lectura de charData en un hilo que en teoría podría observar null, pero una lectura realizada desde dentro de source.vCharAt vería adecuada de los datos…
    • …y es casi seguro que causa cualquier futuro se lee en el hilo para ver sin tener que invocar vCharAt. Para realmente obtener un óptimo rendimiento de la cadena de exigiría un poco de GC ayudar (algo así como la GC hace con WeakReference). Han string perder de campo hash sino que derivan de una clase TelescopingIdentityObject con un protected TelescopingIdentityObject identityInfo;, y GC semántica que si no identityInfo ni identityInfo.identityInfo es null, el campo será reemplazado con el último.
    • Exacto implementación dependerá de exactamente cómo la GC apoyo trabajado, pero este tipo de diseño significaría que las cadenas que se comparan y se encontró que ser igual podría ser consolidados en la equivalencia de los grupos, eliminando la necesidad de comparar de nuevo o de forma redundante a la tienda de su contenido. Por CIERTO, yo pensaba que string se quedó con el original código hash ya que el compilador llama string.hashCode() cuando el uso de cadenas en las sentencias switch. Es que ya no es cierto?
    • El hashCode() funciona como de costumbre for (char c:value) h=31*h+c; pero rara vez se utiliza como la principal hash de los consumidores – (Concurrent)HashMap (pero no Hashtable) llamada hash32() lugar – trate de recorrer en un HashMap que contiene claves de cadena ser 2 invocaciones/instancias/procesos. Personalmente yo no uso case "Str":, es superfluo (y mal estilo) por el diseño como constantes son difíciles de rastrear a diferencia de las enumeraciones. En un flip nota WeakReference no es precisamente fácil en el JIT.
    • Yo esperaría que telescópica referencias no debería ser demasiado difícil para la GC si funciona como lo que yo entiendo de la .NETO DE LA GC. Cuando se encuentra un objeto que aún no se ha copiado, el objeto se copia a una nueva ubicación, un bit se establece en la copia antigua de sincronización de señal word, y el primer 4/8 bytes de la antigua datos de objeto se reemplazan con un puntero a la nueva ubicación. Si el objeto es re-encontered, cualquier referencia se actualiza a la nueva ubicación. Si la primera 4/8 bytes de datos que sucedió, naturalmente, será una referencia a un conocido idéntico objeto, …
    • último comentario: lo que usted explica es una lectura de la barrera. Vienen con algunos de precio fuerte esp. si el cheque no puede ser estimado de manera fiable los predichos por el hardware (y que son necesarios en cada carga, y las cargas son un montón). OTOH leer las barreras son muy buenos si quieres un verdadero concurrente&copia de la GC. Que debe ser mi último mensaje aquí descarrilar está fuera de control ahora.
    • Es ve como String.hashCode podría ser 3,8 veces más rápido con algún manual de desenrollar o la correspondiente JIT mejora. Supongo que podría ser combinada con su longbasado en la optimización.
    • Yo no puedo ver ninguna hash32() en Java 8. Parece haber sido abandonado en favor del uso de TreeNodes para resolver las colisiones.

  4. 6

    Java 9 ejecuta el clasificación de las líneas de un enorme file.txt en java dos veces más rápido que en mi máquina como Java 6 y también sólo las necesidades de 1G de memoria como se ha -XX:+CompactStrings habilitado de forma predeterminada. También, en Java 6, el comprimido cadenas sólo funcionaba para los caracteres ASCII de 7 bits, mientras que en Java 9, es compatible con Latin1 (ISO-8859-1). Algunas operaciones como charAt(idx) podría ser un poco más lento, aunque. Con el nuevo diseño, que también podrían ayudar a otras codificaciones en el futuro.

    Escribí un boletín de noticias sobre esto en El Java De Especialistas De La Newsletter.

    • Bienvenido a Stackoverflow Heinz.
  5. 4

    En OpenJDK 7 (1.7.0_147-icedtea, Ubuntu 11.10), la JVM simplemente se produce un

    No reconocido opción VM ‘UseCompressedStrings’

    cuando JAVA_OPTS (o línea de comandos) contiene -XX:+UseCompressedStrings.

    Parece Oracle realmente quitado la opción.

    • Así que es una mierda. Acabo de enterarme de esta opción, y quería probar en nuestros entornos de pruebas. Manejamos una gran cantidad de Cadenas, y esto podría tener potencialmente reducción de nuestro uso de la memoria.
    • Lo que nos gustaría ver es UTF8, por supuesto.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea