2012-03-09 40 views
16

Tengo una aplicación que tiene ~ 1,000,000 cadenas en la memoria por razones de rendimiento. Mi aplicación consume ~ 200 MB de RAM.Cómo reducir la huella de memoria en aplicaciones intensivas de cadenas .NET?

Quiero reducir la cantidad de memoria consumida por las cadenas.

Sé .NET representa cadenas en codificación UTF-16 (2 bytes por char). La mayoría de las cadenas en mi aplicación contienen caracteres ingleses puros, por lo que su almacenamiento en codificación UTF-8 será 2 veces más eficiente que UTF-16.

¿Hay alguna manera de almacenar una cadena en la memoria con codificación UTF-8 y al mismo tiempo permitir las funciones de cadena estándar? (Mis necesidades incluyen principalmente IndexOf con StringComparison.OrdinalIgnoreCase).

+0

¿Qué pasa con el uso de una matriz de bytes o 'List '? Sin embargo, no estoy seguro de cuánto más difícil sería trabajar con estos objetos para sus necesidades. –

+0

@DxCK, ¿"quiere" o "necesita"? La diferencia es importante para proporcionar respuestas interesantes o prácticas. –

+3

¿Tiene absolutamente que cargar todas las 1,000,000 cadenas en la memoria? ¿Puede proporcionar más detalles sobre qué está haciendo exactamente con todas estas cadenas en la memoria? –

Respuesta

0

¿Qué ocurre si crea su propia clase de cadena UTF-8 (UTF8String?) Y proporciona un molde implícito a String? Estarás sacrificando algo de velocidad por el bien de la memoria, pero eso podría ser lo que estás buscando.

+0

Lo intenté. Convertir nuevamente a String apenas tiene costos de rendimiento. convirtiendo de UTF-8 a UTF-16, luego GC. para 1,000,000 de cuerdas es un costo muy notable. – DxCK

2

¿Qué sucede si lo almacena como bytearray? Simplemente restaure la cadena cuando necesite hacer algunas operaciones en ella. Haría una clase para configurar & obteniendo las cadenas que internamente lo almacena como bytearrays.

a bytearray:

string s = "whatever"; 
byte[] b = System.Text.Encoding.UTF8.GetBytes(s); 

de cadena:

string s = System.Text.Encoding.UTF8.GetString(b); 
+1

Lo intenté. Convertir nuevamente a String apenas tiene costos de rendimiento: asignación de memoria, conversión de UTF-8 a UTF-16, luego GC. para 1,000,000 de cuerdas es un costo muy notable. – DxCK

+0

@DxCK "luego GC" - ¿Qué quieres decir con eso? –

+0

bien, ¿qué quieres ... rendimiento o una huella más pequeña? :) ¿Su aplicación necesita continuamente cada cadena? Si no, tal vez solo almacene cadenas que no se han usado por un tiempo. Haga una clase que haga algún tipo de "recolección de memoria" interna en lugar de recolectar basura. – SpoBo

4

¿Hay una manera de almacenar una cadena en la memoria de codificación UTF-8 al tiempo que permite estándar string> funciones? (Mis necesidades incluyen principalmente IndexOf con StringComparison.OrdinalIgnoreCase).

Puede almacenar como un conjunto de bytes, y proporcionar su propia implementación de IndexOf (ya que la conversión de nuevo a cadena para IndexOf probablemente sea un gran golpe de rendimiento). Utilice las funciones de System.Text.Encoding para eso (la mejor opción sería hacer un paso de compilación para convertirlo en byte, y luego leer las matrices de bytes desde el disco, solo convirtiendo de nuevo a una cadena para su visualización, si es necesario).

Puede almacenarlos en una biblioteca C/C++, lo que le permite usar cadenas de un solo byte. Probablemente no querrás reunirlos, pero posiblemente puedas ordenar los resultados (supongo que hay algún tipo de búsqueda pasando aquí) sin demasiados golpes. C++/CLI puede hacer esto más fácil (al poder escribir el código de búsqueda en C++/CLI, pero la cadena "base de datos" en C++).

O bien, podría volver a visitar los problemas de rendimiento iniciales que necesitan todas las cadenas en la memoria. Una base de datos integrada, indexación, etc. pueden acelerar las cosas y reducir el uso de memoria, y ser más fácil de mantener.

+0

¿Cómo se puede implementar una comparación de personajes IgnoreCase? ¿Hay alguna biblioteca/representación UTF-8 disponible en C/C++? – DxCK

+0

@DxCK el problema que tiene es que si se limita a 8 bits, no admite una gran parte de los idiomas utilizados en el mundo, incluso con C++ y UTF8 –

+1

@Chris S ¿Cómo limita la codificación UTF8 el idioma? – DxCK

11

Desafortunadamente, no se puede cambiar la representación interna .Net de la cadena. Mi suposición es que CLR está optimizado para cadenas multibyte.

Lo que se está tratando es el famoso paradigma de la Space-time tradeoff, que establece que con el fin de liberar memoria que tendrá que usar más procesador, o puede guardar procesador mediante el uso de una cierta memoria.

Dicho esto, échele un vistazo a algunas consideraciones here.Si yo fuera usted, una vez establecido que la ganancia de memoria será suficiente para usted, intente escribir su propia clase de "cadena", que utiliza codificación ASCII. Esto probablemente sea suficiente.

ACTUALIZACIÓN:

Más sobre el dinero, usted debe comprobar este post, "Of memory and strings", por la leyenda Stackoverflow Jon Skeet que se ocupa del problema que se enfrentan. Lo siento, no lo mencioné de inmediato, me llevó algo de tiempo encontrar la publicación exacta de Jon.

2

intente utilizar una base de datos en memoria para "almacenamiento" y SQL para interactuar con los datos ... Por ejemplo, SQLite se puede implementar como parte de la aplicación (consta de 1-2 archivos DLL que se pueden colocar en la misma carpeta que su aplicación) ...

Cuestiones relacionadas