Optimización de la memoria de cadenas

【Prefacio】

Las cadenas a menudo ocupan mucha memoria y hay mucho espacio para la optimización. Al optimizar la memoria, la optimización de la memoria de cadenas es un paso esencial.

Hay tres principios básicos de la optimización de la memoria de cadenas:

1. Reutilizar cadenas para reducir el número de cadenas

2. Reducir la memoria ocupada por cadenas no reutilizables

3. Reduzca la memoria de cadena de GC generada durante el tiempo de ejecución

Bajo estos tres principios básicos, existen algunos métodos específicos.

[Reutilizar cadenas para reducir el número de cadenas]

Hay dos situaciones en las que aparece una gran cantidad de cadenas repetidas: una es que muchas cadenas están escritas en diferentes lugares. Esto puede deberse a que la misma persona escribió en diferentes momentos y se olvidó de los anteriores. Personas diferentes no se conocen entre sí. y diferentes lugares no pueden llamar Passing y otras razones; la segunda es que algunos caracteres se usan repetidamente en el proceso de empalme de cadenas.

La solución es la siguiente:

1. Piscina para residentes

CLR ha realizado un procesamiento especial para la asignación de memoria de cadenas e internamente mantiene un grupo residente. Su esencia interna es mantener un diccionario, la clave es una cadena y el valor es la dirección de referencia de cadena asignada en el montón. Si la cadena se encuentra en el diccionario, devuelva la dirección en valor en lugar de asignar memoria para la cadena y luego devuelva la dirección. ¿Cuándo utilizará el CLR este diccionario?

  • Use valores literales para crear objetos de cadena (los valores literales tienen valores definidos durante la compilación y se pueden encontrar muchas cadenas idénticas)
  • Use string.Intern() para crear objetos de cadena (esto nos permite colocar activamente una cadena en el grupo residente en tiempo de ejecución, la desventaja es que cuando ya no necesitamos usar esta cadena, todavía existe con el grupo residente ocupa parte de la memoria)
  • Empalme de valor literal + valor literal para crear un objeto de cadena

2. Cree su propio diccionario similar al grupo residente

A medida que el proyecto se vuelve cada vez más complejo, el grupo de residentes de CLR siempre no es suficiente y debe crear un diccionario de cadenas similar al grupo de residentes para realizar la reutilización de cadenas.

3. Evite leer el mismo texto o recursos que involucren cadenas en diferentes lugares e intente asegurarse de que solo exista una copia de este recurso en la memoria.

[Reducir la memoria ocupada por cadenas no reutilizables]

Las cadenas que no se pueden reutilizar se deben principalmente a que están vinculadas a recursos o son parte de recursos y deben leerse en el programa en tiempo de ejecución Para reducir la memoria de estas cadenas, las cadenas deben tener una longitud simplificada.

Usamos cadenas para representar una situación o una cosa. Las cadenas de diferentes situaciones o diferentes cosas son únicas, lo que puede garantizar que las cadenas y las situaciones se correspondan uno a uno.

Antes de eso, debe comprender la composición de la cadena : (tome 32 bits como ejemplo)

1. Como tipo de referencia, una parte indispensable: el encabezado de referencia (encabezado de objeto) requiere 8 bytes (incluido el bloque de índice de sincronización de 4 bytes y el puntero de objeto de tipo de 4 bytes)

2. Un campo int32 para registrar la longitud de la cadena (entre varias operaciones de cadena, la velocidad para encontrar la longitud es la más rápida, solo consulta directamente. Esto también limita la longitud máxima de una cadena)

3. El caracter nulo al final ocupa dos bytes

4. La parte restante es el contenido de caracteres almacenado en el búfer de caracteres, que termina con un carácter nulo

Por lo tanto, el tamaño de memoria que ocupa una cadena es 14(8+4+2)+2*número de caracteres. Por ejemplo, la cadena "HelloWorld" ocupa 34 bytes de memoria. Tenga en cuenta que se adopta la codificación UTF-16 para el tipo de cadena en C#, por lo que un carácter en el tipo de cadena ocupa 2 bytes.

Tenga en cuenta que este es solo el tamaño de memoria requerido por la cadena, porque el GC de .NET usa alineación de memoria de 32 bits (es decir, toda la memoria asignada es un múltiplo entero de 4 bytes), por lo que el tamaño de memoria real ocupado por "HelloWorld" es 36 bytes.

(Una cadena cadena vacía. Vacío ocupa 8 bytes)

La solución es la siguiente:

1. Con la premisa de mantener el significado de la cadena, intente simplificar la cadena, por ejemplo, reemplace chino con CN, etc.

2. Algunas cadenas no se pueden simplificar, como las rutas. En este momento, puede aplicar un hash a las cadenas para asegurarse de que cada cadena corresponda a un valor hash único.

3. En el caso de cadenas limitadas, use byte, uint y otros tipos en lugar de cadenas y cree una tabla de mapeo. Por ejemplo, no hay más de 8 tipos de cadenas, use tipo byte, etc.

4. Use byte[] en lugar de cadena

5. Al analizar el negocio, algunas cadenas no aparecen al mismo tiempo y se pueden cargar a pedido

6. Descomprimir cadenas largas pero de uso poco frecuente (tenga en cuenta que habrá rendimiento y consumo de GC)

A través de estos 6 métodos, la memoria ocupada por cadenas generalmente se puede optimizar en más del 80%.

[Reducir la memoria de cadena de GC generada en tiempo de ejecución]

1. Una es prestar atención a la posible aparición de cadenas GC al escribir código , especialmente en lugares de alta frecuencia.

2. En algunos lugares, GC es inevitable, como la operación de número a cadena. En este momento, una memoria residente se puede abrir por separado. Al realizar operaciones de cadena, todas las operaciones se realizan en esta memoria y esta memoria se reutiliza. Se puede evitar GC, que también es el principio del esquema de cadena 0GC. En términos generales, la solución zstring es suficiente. La dirección del proyecto es la siguiente: GitHub - 871041532/zstring: C# string zero GC complementy solution

[Operaciones relacionadas con el rendimiento de cuerdas]

1. Para crear una cadena vacía, use string s = string.Empty en lugar de string s = ""

2. Stringbuilder para empalme de cuerdas de alta frecuencia

3. Los métodos como ToUpper y ToLower regenerarán la cadena para ver si se puede evitar.

4. Cuando juzgue verdadero, use "valor" == la cadena es la más rápida, cuando juzgue falso, use "valor".Equals (cadena) es la más rápida

5. Operación de comparación de cadenas

Supongo que te gusta

Origin blog.csdn.net/enternalstar/article/details/126842396
Recomendado
Clasificación