Donc, ce fil est tout le monde parle et pas de chiffres permet donc des mesures de discussion. J'ai mesuré ces métriques en calculant le temps moyen de chaque méthode sur 10 tests avec 10 millions d'itérations chacun en mode Debug puis Release (non optimisé puis optimisé)):
(Debug) coulée Méthode: ~ 32 ms Méthode d'attribution: ~ 26 ms
(sortie) coulée Méthode: ~ 20 ms Méthode de répartition: ~ 22 ms
Qu'est-ce que Il est également intéressant de comparer ces métriques à un code similaire avec C++ géré en utilisant seulement gcnew et les résultats sont très différents.
Même configuration à nouveau. Sauf en comparant la méthode de coulée: "IntPtr^ptr = (IntPtr) i;" vs la méthode d'allocation: "IntPtr^ptr = (IntPtr) i;".
(Mise au point) casting Méthode: ~ 91ms Allocation Méthode: ~ 127ms
(Release) casting Méthode: ~ 22ms Méthode d'allocation: ~ 124ms
Maintenant, si vous gratter la tête en disant: Eh bien, pourquoi C# est-il tellement plus rapide que le C++ géré et la réponse est que non. Le moyen le plus efficace d'utiliser IntPtr est le type de valeur et non une référence à un type de valeur. Par exemple comme si "IntPtr ptr = (IntPtr) i;". Cela vous donnerait ~ 24ms (Debug more) ou (~ 22 Release mode). Voyez comment il a été optimisé au-dessus par le compilateur pour obtenir le 22ms plutôt que le 90ms. Conclusion en C#, sauf si vous cherchez un code vraiment très serré, cela n'a pas d'importance. Je pense qu'avec mon code dans Release, c'était en fait en optimisant le casting, car commenter le casting donnait le même ~ 22ms. Mais pour la plupart compilateur a votre dos sur celui-ci en C# bien au moins VS 2010 fait. Cependant, dans Managed C++/CLI, si vous observez du code avec des contraintes de performances minimales, faites attention. Le compilateur n'optimisera pas automatiquement les allocations gcnew à l'approche casting et il est presque 6 fois plus rapide ... J'ai en fait rencontré ce problème particulier en C++/CLI qui est ce qui m'a amené à poster sur ce thread quand il s'agissait d'audio en temps réel En traitement. Mon code (C#): (Mon code C++ géré était très similaire sauf que je devais écrire Average() moi-même et utiliser la console pour sortir plutôt que des boîtes de message).
static void Main()
{
List<int> castTimings = new List<int>();
List<int> allocTimings = new List<int>();
for (int i = 0; i < TEST_RUNS; ++i)
{
castTimings.Add(RunCastMethod().Milliseconds);
allocTimings.Add(RunAllocationMethod().Milliseconds);
}
MessageBox.Show(string.Format("Casting Method took: {0}ms", castTimings.Average()));
MessageBox.Show(string.Format("Allocation Method took: {0}ms", allocTimings.Average()));
}
private static TimeSpan RunAllocationMethod() {
DateTime start = DateTime.Now;
for (int i = 0; i < TEST_ITERATIONS; ++i)
{
IntPtr ptr = new IntPtr(i);
}
return (DateTime.Now - start);
}
private static TimeSpan RunCastMethod()
{
DateTime start = DateTime.Now;
for (int i = 0; i < TEST_ITERATIONS; ++i)
{
IntPtr ptr = (IntPtr) i;
}
return (DateTime.Now - start);
}
Le fait que IntPtr soit un type de valeur ne signifie pas que new n'alloue pas de mémoire. En fait, l'utilisation de new devrait être préférée pour s'assurer que la structure est correctement initialisée. –
Je pense que ce que Pavel voulait dire, c'est qu'il n'utilise pas de mémoire qui n'aurait pas été utilisée autrement. Évidemment, copier un type de valeur signifiera que plus de mémoire sera utilisée :) – Thorarin
Il n'y a absolument aucun avantage à utiliser (ou ne pas utiliser) 'new' pour s'assurer que la structure est correctement initialisée. Pour commencer, vous ne pouvez pas avoir une "structure mal initialisée" en premier lieu, puisque le compilateur appliquera l'initialisation pour les locals, et par défaut initialisera tout le reste. –