Heredé un fragmento de código que hace un uso intensivo de las conversiones String -> byte [] y viceversa para algún código de serialización nacional. Esencialmente, los objetos de Java saben cómo convertir sus partes constituyentes en cadenas que luego se convierten en un byte []. Dicha matriz de bytes se pasa luego a través de JNI al código de C++ que reconstituye el byte [] en C++ std :: cadenas y los utiliza para arrancar objetos de C++ que reflejan los objetos de Java. Hay un poco más, pero esta es una vista de alto nivel de cómo funciona este código; La comunicación funciona así en ambas direcciones, de modo que la transición C++ -> Java es una imagen especular de la transición Java -> C++ que mencioné anteriormente.¿Alguna sugerencia sobre cómo mejorar el rendimiento de una conversión de Java String a byte []?
Una parte de este código, la conversión real de una cadena en un byte [], se muestra inesperadamente en el generador de perfiles como la quema de una gran cantidad de CPU. De acuerdo, hay una gran cantidad de datos que se transfieren, pero esto es un cuello de botella inesperado.
El esquema básico del código es el siguiente:
public void convertToByteArray(String convert_me, ByteArrayOutputStream stream)
{
stream.write(convert_me.getBytes());
}
No es un poco más a la función pero no mucho. La función anterior se llama una vez por cada objeto String/Stringified y después de que todos los componentes se escriben en ByteArrayOutputStream, ByteArrayOutputStream se convierte en un byte []. Romper lo anterior en una versión más amigable con el perfil extrayendo la llamada convert_me.getBytes()
muestra que más del 90% del tiempo en esta función se gasta en la llamada getBytes().
¿Hay alguna forma de mejorar el rendimiento de la llamada a getBytes() o existe otra forma, potencialmente más rápida, de lograr la misma conversión?
El número de objetos que se están convirtiendo es bastante grande. En las ejecuciones de perfiles que utilizan solo un pequeño subconjunto de los datos de producción, veo algo así como más de 10 millones de llamadas a la función de conversión anterior.
Debido al hecho de que estamos muy cerca de liberar el proyecto en la producción, hay algunas soluciones que no son posibles en este punto en el tiempo:
- reescribir la interfaz de serialización para pasar solo Cadena de objetos a través de la capa JNI. Esta es la manera obvia (para mí) de mejorar la situación, pero requeriría una reingeniería importante de la capa de serialización. Dado el hecho de que entraremos en la UAT a principios de esta semana, es demasiado tarde para hacer este tipo de cambio complejo. Es mi mejor tarea para el próximo lanzamiento, así que estará listo; Sin embargo, necesito una solución hasta entonces, pero hasta ahora el código está funcionando, se ha utilizado durante años y tiene la mayoría de las fallas. Bueno, aparte de la actuación.
- Cambiar la JVM (actualmente 1.5) tampoco es una opción. Desafortunadamente esta es la JVM predeterminada que está instalada en las máquinas del cliente y desafortunadamente no es posible actualizar a 1.6 (que podría ser más rápido en este caso). Cualquiera que haya trabajado en grandes organizaciones probablemente entienda por qué ...
- Además de esto, ya nos estamos topando con limitaciones de memoria, por lo que intentamos almacenar en caché al menos las cadenas más grandes y su representación de matriz de bytes, a la vez que una solución potencialmente elegante , es probable que cause más problemas de los que resolverá
Hola Timo, sólo una pregunta tonta es la herramienta que perfilador ha utilizado? –
@Castanho - Utilicé IBM Rational's PurifyPlus. –