Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

143
Visualizações
Weird performance behavior of .NET dictionary insertion

I have two dictionaries with different value types: Dictionary<int, string[]> and Dictionary<int, int[]>. Suppose we generate random arrays in a loop and insert them to the dictionaries (in 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();

Note the last two lines of the for loop. When I run the above code, it takes about 13.9 sec on my machine. Now, when I comment out only (1), then it takes about 13.7 sec. And if I comment out only (2), then it takes about 20 sec. In other words, by removing (2) it becomes much slower! I repeated this multiple times, and I can confirm that the behavior is consistent.

Can anyone please explain how this is even possible?

I did this experiment because I noticed that inserting string[] is slower than inserting int[] even though I am using the same key in the two dictionaries. I would like to know why inserting string [] can be slower than inserting int[], too.

So my quetion is twofold: (1) how come removing a line from the above code can make things slower, (2) why inserting string[] is slower than inserting int[]?


FYI, I am using the latest .NET 5 (5.0.103). I tried the code on both Windows and Linux, and the behavior was the same. I consistently see the same problem using either debug or release mode.


When I diff ILs of commented out version vs. original, the commented out version has no call to set_Item function of the dictionary as expected. Other things are more or less the same.

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

The above part was removed when I commented out (2) for example.


To help repro this problem, I created a simple repo with Benchmark.NET: https://github.com/sangkilc/TestDictionary. In this repo, I reduced the number of iterations (from 40M to 4M) because it takes too long.

On my machine the results are:

.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 |

As per @TheodorZoulias's observation, if I modify d2 to a 2D array, then the difference becomes more significant:

|   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 Respostas
Responde à pergunta

0

This is not an answer, just wanted to show off some pictures

I have the code compiled in Release for two of your scenarios:

  • With both (1) and (2)
  • With (1) only

Note that I removed Stopwatch related code, because we're only interested in Dictionary.

I have dotTrace on my machine, so I got some profiling results (line-by-line).

For the both scenario:

By Thread Tree: enter image description here

By Methods: enter image description here

For the (1) only scenario:

By Thread Tree: enter image description here

By Methods: enter image description here

Since you mentioned that the pattern is consistent, I ran the profiling only once.

From the results, we could tell functions related to Dictionary are not the main contributors to the so called "weird performance behavior", GC probably is.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda