Quel est le plus rapide: (int), Convert.ToInt32 (x) ou Int32.Parse (x)?

Lequel du code suivant est le plus rapide / la meilleure pratique pour convertir un object x?

int myInt = (int)x; 

ou

 int myInt = Convert.ToInt32(x); 

ou

 int myInt = Int32.Parse(x); 

ou dans le cas d’une chaîne ‘s’

 int myInt; Int32.TryParse(s, out myInt); 

Je suis curieux de savoir qui effectue le plus rapide pour les types de données qui ont une méthode dans Convert, pas seulement ints. Je viens juste d’utiliser int comme exemple.

Edit: Ce cas est venu de récupérer des informations à partir d’une firebase database. Est-ce que (int) fonctionnera toujours le plus rapidement?

À partir de certains tests, lorsque l’object x = 123123123, int effectue le plus rapide, comme beaucoup l’ont dit. Lorsque x est une chaîne, Parse exécute le plus rapidement (note: le lancer lance une exception). Ce que je suis vraiment curieux, c’est la façon dont ils fonctionnent lorsque la valeur est récupérée de la manière suivante:

 foreach(DataRow row in someTable.Rows) { myInt = (int)row["some int value"]; myInt2 = Int.Parse(row["some int value"]); myInt2 = Convert.ToInt32(row["some int value"]); } 

Pourquoi ne pas simplement essayer quelques milliers de fois?

(cela vaut pour tous “Qu’est-ce qui est le plus rapide:” questions)


Hmmm, beaucoup de downvotes au fil des ans … Je suppose que je devrais développer cette réponse.

La déclaration ci-dessus a été faite avec une certaine désinvolture dans ma jeunesse, mais je suis toujours d’accord avec son sentiment. Cela ne vaut pas la peine de passer du temps à créer une question SO demandant aux autres ce qu’ils pensent être plus rapide sur deux ou trois opérations qui prennent moins de 1 ms chacune.

Le fait que l’on puisse prendre un cycle ou deux plus long que l’autre sera presque certainement négligeable dans son utilisation quotidienne. Et si vous remarquez un problème de performance dans votre application lorsque vous convertissez des millions d’objects en ints, vous pouvez définir le code actuel et vous pourrez facilement tester si la conversion int est en fait le goulot d’étranglement.

Et alors qu’aujourd’hui, c’est le convertisseur object-int, demain, vous penserez peut-être que votre convertisseur object-DateTime prend beaucoup de temps. Voulez-vous créer une autre question SO pour savoir quelle est la méthode la plus rapide?

En ce qui concerne votre situation (sans doute depuis longtemps résolue à ce jour), comme mentionné dans un commentaire, vous interrogez une firebase database, donc la conversion object-int est la moindre de vos préoccupations. Si j’étais vous j’utiliserais n’importe laquelle des méthodes de conversion que vous avez mentionnées. Si un problème survient, j’isolerais l’appel, en utilisant un profileur ou une journalisation. Alors, quand je constate que la conversion object-int se fait un million de fois et que le temps total pris par cette conversion semble relativement élevé, je passerais à une méthode de conversion et à un re-profil différents. Choisissez la méthode de conversion qui prend le moins de temps. Vous pourriez même tester ceci dans une solution séparée, ou même LINQPad, ou Powershell etc.

Cela dépend de ce que vous attendez x

Si x est un boxed int alors (int)x est le plus rapide.

Si x est une chaîne mais est certainement un nombre valide alors int.Parse(x) est le meilleur

Si x est une chaîne mais qu’elle n’est peut-être pas valide, alors int.TryParse(x) est beaucoup plus rapide qu’un bloc try-catch.

La différence entre Parse et TryParse est négligeable sauf pour les plus grandes boucles.

Si vous ne savez pas ce que x est (peut-être une chaîne ou un int en boîte), alors Convert.ToInt32(x) est le meilleur.

Ces règles généralisées sont également vraies pour tous les types de valeur avec les méthodes statiques Parse et TryParse.

Plus rapide! = Meilleure pratique!

Par exemple, (int) est certainement le plus rapide car il s’agit d’un opérateur plutôt que d’un appel de fonction, mais il ne fonctionnera que dans certaines situations.

La meilleure pratique consiste à utiliser le code le plus lisible qui n’a pas d’impact négatif sur vos performances, et 99 fois sur 100, une conversion en nombre entier n’améliore pas les performances de votre application. Si c’est le cas, utilisez la conversion la plus appropriée et la plus étroite possible. Parfois, c’est (int) . Parfois, c’est TryParse() . Parfois, c’est Convert.ToInt32() .

Si vous savez que les données sont définitivement int, alors int myInt = (int)x; devrait être l’option la plus rapide. Sinon, TryParse vous aidera à bien faire les choses sans la lenteur des exceptions.

BTW:

(int) ne libère que les boîtes plus rapidement,

(int) IL =

  .locals init ( [0] object x, [1] int32 Y) L_0000: ldc.i4.1 L_0001: box int32 L_0006: stloc.0 L_0007: ldloc.0 L_0008: unbox int32 L_000d: ldobj int32 L_0012: stloc.1 L_0013: ret 

Convert.Toint32 =

 .locals init ( [0] object x, [1] int32 Y) L_0000: ldc.i4.1 L_0001: box int32 L_0006: stloc.0 L_0007: ldloc.0 L_0008: call object [mscorlib]System.Runtime.ComstackrServices.RuntimeHelpers::GetObjectValue(object) L_000d: call int32 [mscorlib]System.Convert::ToInt32(object) L_0012: stloc.1 L_0013: ret 

Lorsque je me pose des questions sur les différences de performances entre différentes manières de faire quelque chose de spécifique, je fais généralement une nouvelle entrée dans MeasureIt, un téléchargement gratuit d’un excellent article MSDN de Vance Morrison. Pour plus d’informations, reportez-vous à l’article.

En ajoutant un simple bit de code à MeasureIt, j’obtiens les résultats ci-dessous qui comparent les timings réels des différentes méthodes de conversion en int. Notez que la conversion de chaîne en int lancera une exception et ne sera pas valide. J’ai donc ajouté les permutations qui me paraissaient intéressantes.


 Nom Médiane Moyenne StdDev Min Max Échantillons       
 IntCasts: Copie [comptage = 1000 échelle = 10.0] 0.054 0.060 0.014 0.054 0.101 10       
 IntCasts: Cast Int [count = 1000 scale = 10.0] 0.059 0.060 0.007 0.054 0.080 10       
 IntCasts: Objet Cast [nombre = 1000 échelle = 10.0] 0.097 0.100 0.008 0.097 0.122 10       
 IntCasts: int.Parse [count = 1000 scale = 10.0] 2.721 3.169 0.850 2.687 5.473 10       
 IntCasts: Convert.ToInt32 [count = 1000 scale = 10.0] 3.221 3.258 0.067 3.219 3.418 10     

Pour trouver les meilleures performances pour les différents types qui vous intéressent, étendez simplement le code ci-dessous, ce qui est littéralement tout ce que je devais append à MeasureIt pour générer le tableau ci-dessus.

 static unsafe public void MeasureIntCasts() { int result; int intInput = 1234; object objInput = 1234; ssortingng strInput = "1234"; timer1000.Measure("Copy", 10, delegate { result = intInput; }); timer1000.Measure("Cast Object", 10, delegate { result = (int)objInput; }); timer1000.Measure("int.Parse", 10, delegate { result = int.Parse(strInput); }); timer1000.Measure("Convert.ToInt32", 10, delegate { result = Convert.ToInt32(strInput); }); } 

La meilleure pratique serait TryParse, et en voyant le résultat, si cela fonctionnait – sinon vous pourriez obtenir des exceptions

Lors de l’optimisation d’une grid de données liées dans .Net 2, j’ai trouvé que presque la moitié du temps était consacré aux méthodes ToSsortingng () de divers objects, qui étaient ensuite utilisées comme entrées des opérations de conversion. En isolant ces cas et en les convertissant au bon type, dans la mesure du possible (étant donné qu’il s’agissait de lignes extraites d’une firebase database et que les types pouvaient être utilisés), la rapidité de cette opération de liaison de données s’est considérablement accrue.

Donc, si vous connaissez le type de la chose au premier plan et que vous frappez suffisamment le morceau de code, cela vaut la peine de le lancer directement au lieu de le convertir si nécessaire.

En prolongeant le test d’Eric Cosky par des alternatives de Sam Allen , j’ai trouvé que si vous savez que votre chaîne est un entier valide, alors l’parsing par vous-même est beaucoup plus rapide.

J’ai prolongé le test par les cas suivants:

  timer1000.Measure("IntParseFast", 10, delegate { result = Misc.IntParseFast(strInput); }); timer1000.Measure("IntParseUnsafe", 10, delegate { result = Misc.IntParseUnsafe(strInput); }); 

Avec les implémentations suivantes:

 public static int IntParseFast(ssortingng value) { int result = 0; int length = value.Length; for (int i = 0; i < length; i++) { result = 10 * result + (value[i] - 48); } return result; } public unsafe static int IntParseUnsafe(string value) { int result = 0; fixed (char* v = value) { char* str = v; while (*str != '\0') { result = 10 * result + (*str - 48); str++; } } return result; } 

Je reçois les résultats suivants:

 IntCaint.Parse 5,495 IntCaConvert.ToInt32 5,653 IntCaIntParseFast 1,154 IntCaIntParseUnsafe 1,245 

Pas sûr de la performance, mais ces méthodes ne sont pas du tout les mêmes. Parse et TryParse fonctionnent tous les deux avec ssortingng, la représentation Ssortingng d’un object est analysée (voir MSDN).

Convertit la représentation sous forme de chaîne d’un nombre en son équivalent entier signé de 32 bits.

Je ne suis pas sûr du casting et de la classe Convert , mais la dissortingbution ne concerne que les objects qui sont déjà des entiers, mais pas fortement typés.

Matthias

Si vous aviez besoin de la vitesse supplémentaire, il serait facile de tester les différentes options. Comme vous ne les testez pas, vous ne devez pas en avoir besoin. Ne perdez pas votre temps avec des micro-optimisations inutiles!

(int) la conversion sur la chaîne ne fonctionnera pas, donc je ne la teste pas. Convert.ToInt32 reflète comme test la valeur à null et THEN appelant int.Parse, devrait donc en général être plus lent que int.Parse ().

 foreach(DataRow row in someTable.Rows) { myInt = (int)row["some int value"]; myInt2 = Int.Parse(row["some int value"]); myInt2 = Convert.ToInt32(row["some int value"]); } 

Pour cet exemple, si la valeur provenant de la table est bien une valeur int ou une valeur de firebase database comparable, vous pouvez utiliser la valeur

 myInt = (int)row["some int value"]; 

serait le plus efficace, et donc le plus rapide parce que la

 row["some int value"]; 

sera une instance de type valeur int encadrée à l’intérieur d’une instance d’object de type référence, donc l’utilisation de la conversion de type explicite sera la plus rapide car d’autres personnes ont dit qu’il s’agissait d’une opération et non d’une fonction, réduisant ainsi les opérations de processeur requirejses. Un appel à une méthode de conversion ou d’parsing nécessiterait des opérations de processeur supplémentaires et ne serait donc pas aussi rapide.

ce n’est pas vrai. La conversion rapide est la conversion directe:

 int i = (int) ssortingngData; watch.Elapsed = {00:00:00.1732388} watch2.Elapsed= {00:00:00.0878196} // Mesary start Stopwatch watch = new Stopwatch(); watch.Start(); for (int f = 1; f < 1000000; f++) { item.Count = FastInt32.IntParseFast(dt.Rows[i]["TopCount"]); } // Execute the task to be timed watch.Stop(); Console.WriteLine("Elapsed: {0}", watch.Elapsed); Console.WriteLine("In milliseconds: {0}", watch.ElapsedMilliseconds); Console.WriteLine("In timer ticks: {0}", watch.ElapsedTicks); // Mesary end // Mesary start Stopwatch watch2 = new Stopwatch(); watch2.Start(); for (int n = 1; n < 1000000; n++) { item.Count = (int)(dt.Rows[i]["TopCount"]); } // Execute the task to be timed watch2.Stop(); Console.WriteLine("Elapsed: {0}", watch2.Elapsed); Console.WriteLine("In milliseconds: {0}", watch2.ElapsedMilliseconds); Console.WriteLine("In timer ticks: {0}", watch2.ElapsedTicks); // Mesary end 

Quelqu’un a déjà fait l’parsing comparative. Voici les résultats. Le moyen le plus rapide si vous savez ce que vous convertissez sera toujours un int valide, c’est d’utiliser la méthode suivante (à laquelle quelques personnes ont répondu ci-dessus):

 int value = 0; for (int i = 0; i < str.Length; i++) { value = value * 10 + (str[i] - '0'); } 

Les autres techniques évaluées étaient les suivantes:

  • Convert.ToInt32
  • Int32.TryParse
  • int.Parse

Au final, ils finissent tous par appeler:

 System.Number.ParseInt32(ssortingng s, NumberStyles style, NumberFormatInfo info); 

Donc, en résumé, il n’y aura aucune différence.

Jetez un coup d’oeil dans .Net Reflector pour voir ceci.