je rencontre ce problème bizarre performance:application C# les performances du processeur ralentit de façon drastique lorsque le programme crée un grand nombre d'objets
J'ai une application C# qui crée des millions d'objets C#.
Dans une partie non liée du code, l'application ne une œuvre qui ne dépend pas des données allouées à l'étape 1.
Le temps CPU semblent être en corrélation avec le nombre d'objets créé à l'étape 1.
J'ai écrit un simple cas C# qui reproduit mon problème. slowdown
La commande est appelée avec le nombre de millions d'objets chaîne créés avant l'appel de la méthode DoMyWork()
. Comme vous pouvez le voir, la même méthode DoMyWork()
peut prendre jusqu'à 3 s si 200M de chaînes sont instanciées.
- Quelque chose me manque dans la langue?
- Supposons que la limite de mémoire physique n'est pas atteinte, y a-t-il un nombre maximum d'objets qui ne devraient pas être atteints sinon le CLR ralentirait?
j'ai couru mon test sous Windows 10 sur Intel Core i7-6700 et mon programme est une version de la console intégrée en mode 32 bits (VS 2017 - fw 4.6.1):
slowdown 0 Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 4 ms Allocating 40000 hashtables: 15 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 5 ms Allocating 40000 hashtables: 5 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 18 ms Allocating 40000 hashtables: 10 ms Allocating 40000 hashtables: 19 ms
ralentissement 0 utilise ~ 30M
slowdown 200 Allocating 40000 hashtables: 392 ms Allocating 40000 hashtables: 1120 ms Allocating 40000 hashtables: 3067 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 31 ms Allocating 40000 hashtables: 418 ms Allocating 40000 hashtables: 15 ms Allocating 40000 hashtables: 2 ms Allocating 40000 hashtables: 18 ms Allocating 40000 hashtables: 416 ms
ralentissement 200 utilisations ~ 800M
using System;
using System.Diagnostics;
using System.Collections;
namespace SlowDown
{
class Program
{
static string[] arr;
static void CreateHugeStringArray(long size)
{
arr = new string[size * 1000000];
for (int i = 0; i < arr.Length; i++) arr[i] = "";
}
static void DoMyWork()
{
int n = 40000;
Console.Write("Allocating " + n + " hashtables: ");
Hashtable[] aht = new Hashtable[n];
for (int i = 0; i < n; i++)
{
aht[i] = new Hashtable();
}
}
static void Main(string[] args)
{
if (0 == args.Length) return;
CreateHugeStringArray(Convert.ToInt64(args[0]));
for (int i = 0; i < 10 ; i++)
{
Stopwatch sw = Stopwatch.StartNew();
DoMyWork();
sw.Stop();
Console.Write(sw.ElapsedMilliseconds + " ms\n");
}
}
}
}
Dans votre exemple, vous ne créez pas « millions d'objets C# ». Vous créez un grand nombre de chaînes, et chaque élément du tableau pointe vers le même objet chaîne (voir string interning). – dymanoid
Comment cela fonctionne si vous essayez d'ajouter un entier à integer dans 'DoMyWork', car il y a une opération de boxe impliquée dans la logique existante. Vous pouvez également utiliser 'StringBuilder' tout en manipulant plusieurs fois la même chaîne. –
Ajoutez 'GC.Collect()' juste après 'CreateHugeStringArray' et voyez si vous obtenez toujours les mêmes heures. –