Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

144
Vistas
Comportamiento de rendimiento extraño de la inserción del diccionario .NET

Tengo dos diccionarios con diferentes tipos de valores: Dictionary<int, string[]> y Dictionary<int, int[]> . Supongamos que generamos matrices aleatorias en un bucle y las insertamos en los diccionarios (en C#).

 var d1 = new Dictionary<int, string[]>(); var d2 = new Dictionary<int, int[]>(); var sw = Stopwatch.StartNew(); for (int i = 0; i < 40000000; i++) { string[] sarr = new string[10]; for (int j = 0; j < 10; j++) { sarr[j] = j.ToString(); } int[] iarr = new int[10]; for (int j = 0; j < 10; j++) { iarr[j] = j; } d1[i] = sarr; // (1) d2[i] = iarr; // (2) } sw.Stop();

Tenga en cuenta las dos últimas líneas del bucle for. Cuando ejecuto el código anterior, toma alrededor de 13,9 segundos en mi máquina. Ahora, cuando comento solo (1), tarda unos 13,7 segundos. Y si solo comento (2), entonces toma alrededor de 20 segundos. En otras palabras, al eliminar (2) ¡se vuelve mucho más lento! Repetí esto varias veces y puedo confirmar que el comportamiento es consistente.

¿Alguien puede explicar cómo esto es posible?

Hice este experimento porque noté que insertar string[] es más lento que insertar int[] aunque estoy usando la misma clave en los dos diccionarios. Me gustaría saber por qué insertar string [] también puede ser más lento que insertar int[] .

Entonces, mi pregunta es doble: (1) ¿cómo es que eliminar una línea del código anterior puede hacer que las cosas sean más lentas, (2) por qué insertar string[] es más lento que insertar int[] ?


FYI, estoy usando la última versión de .NET 5 (5.0.103). Probé el código tanto en Windows como en Linux, y el comportamiento fue el mismo. Constantemente veo el mismo problema usando el modo de depuración o de lanzamiento.


Cuando diferencio los IL de la versión comentada frente a la original, la versión comentada no tiene una llamada a la función set_Item del diccionario como se esperaba. Las demás cosas son más o menos iguales.

 IL_0079: ldloc.1 // dictionary2 IL_007a: ldloc.3 // key IL_007b: ldloc.s numArray IL_007d: callvirt instance void class [System.Collections]System.Collections.Generic.Dictionary`2<int32, int32[]>::set_Item(!0/*int32*/, !1/*int32[]*/) IL_0082: nop

La parte anterior se eliminó cuando comenté (2), por ejemplo.


Para ayudar a reproducir este problema, creé un repositorio simple con Benchmark.NET: https://github.com/sangkilc/TestDictionary . En este repositorio, reduje la cantidad de iteraciones (de 40 millones a 4 millones) porque lleva demasiado tiempo.

En mi máquina los resultados son:

 .NET Core SDK=5.0.103 [Host] : .NET Core 5.0.3 (CoreCLR 5.0.321.7212, CoreFX 5.0.321.7212), X64 RyuJIT DefaultJob : .NET Core 5.0.3 (CoreCLR 5.0.321.7212, CoreFX 5.0.321.7212), X64 RyuJIT | Method | Mean | Error | StdDev | |--------- |--------:|---------:|---------:| | TestBoth | 1.269 s | 0.0222 s | 0.0208 s | | TestOne | 1.381 s | 0.0257 s | 0.0241 s |

Según la observación de @TheodorZoulias, si modifico d2 a una matriz 2D, la diferencia se vuelve más significativa:

 | Method | Mean | Error | StdDev | |--------- |--------:|---------:|---------:| | TestBoth | 1.137 s | 0.0195 s | 0.0163 s | | TestOne | 1.373 s | 0.0246 s | 0.0345 s |
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Esta no es una respuesta, solo quería mostrar algunas fotos.

Tengo el código compilado en Release para dos de sus escenarios:

  • Con (1) y (2)
  • Con (1) solo

Tenga en cuenta que eliminé el código relacionado con Stopwatch , porque solo estamos interesados en Dictionary .

Tengo dotTrace en mi máquina, así que obtuve algunos resultados de perfiles (línea por línea).

Para ambos escenarios:

Por árbol de hilos: ingrese la descripción de la imagen aquí

Por métodos: ingrese la descripción de la imagen aquí

Para el (1) único escenario:

Por árbol de hilos: ingrese la descripción de la imagen aquí

Por métodos: ingrese la descripción de la imagen aquí

Como mencionó que el patrón es consistente, ejecuté el perfilado solo una vez.

A partir de los resultados, podríamos decir que las funciones relacionadas con Dictionary no son las principales contribuyentes al llamado "comportamiento de rendimiento extraño", probablemente GC lo sea.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda