quale sarebbe più veloce?Quanto è costoso un cast GUID e confronto rispetto a un confronto di stringhe
bool same=(Guid)Identifier==id;
bool same=String.Equals(string1,string2, StringComparison.OrdinalIgnoreCase);
quale sarebbe più veloce?Quanto è costoso un cast GUID e confronto rispetto a un confronto di stringhe
bool same=(Guid)Identifier==id;
bool same=String.Equals(string1,string2, StringComparison.OrdinalIgnoreCase);
Ho usato questo codice:
object victim = Guid.Empty;
Guid target = Guid.NewGuid();
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 10000000; i++){
bool equal = ((Guid) victim) == target;
}
Console.WriteLine("Direct cast : {0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < 10000000; i++)
{
bool equal = Guid.Equals(victim, target);
}
Console.WriteLine("Guid.Equals : {0}", sw.Elapsed);
sw.Reset(); sw.Start();
string a = victim.ToString(); // as suggested by Mikael
string b = target.ToString();
for (int i = 0; i < 10000000; i++)
{
bool equal = String.Equals(a, b, StringComparison.OrdinalIgnoreCase);
}
Console.WriteLine("String.Equals : {0}", sw.Elapsed);
Console.ReadLine();
e ottenuto questo risultato per diversi valori (scenario migliore):
object victim = Guid.Empty;
Guid target = Guid.NewGuid();
// Direct cast : 00:00:00.1164198
// Guid.Equals : 00:00:02.1268147
// String.Equals : 00:00:00.4129527 // oh my!
E questo risultato per lo stesso valore (scenario peggiore)
object victim = Guid.Empty;
Guid target = Guid.Empty;
// Direct cast : 00:00:00.2793173
// Guid.Equals : 00:00:03.5625948
// String.Equals : 00:00:01.7564302
questa è la migliore risposta in quanto mostra effettivamente un punto di riferimento ... –
Il benchmark esce dal confronto sul byte 1 che è lo sforzo migliore. Se si confrontano ancora più byte, i tempi potrebbero differire ancora di più. Ma la differenza di tempo non è enorme come pretendi, dato che hai incluso .ToString() nel ciclo. string a = victim.ToString(); string b = target.ToString(); per (int i = 0; i <10000000; i ++) { bool uguale = String.Equals (a, b, StringComparison.OrdinalIgnoreCase); } –
@ Mikael, buoni consigli; il tuo suggerimento ha portato un enorme miglioramento sulle prestazioni di string.equals. –
Un Guid Guid == utilizzerà il codice come:
public bool Equals(Guid g)
{
if (g._a != this._a)
{
return false;
}
if (g._b != this._b)
{
return false;
}
mentre la stringa di confrontare nel tuo esempio utilizzerà un confronto puntatore non sicuro.
Senza il benchmark, sospetto che il Guid sarà più veloce, ma stiamo parlando di marginale. E hai davvero bisogno di aumentare il numero di confronti con i milioni di dollari per farli avere importanza.
Entrambi i confronti scoppiano in anticipo, ovvero da sinistra a destra, in modo da influire anche sulla velocità. Il confronto delle stringhe ha più controlli prima che avvenga il confronto e un'altra chiamata al metodo.
cosa lo rende più sicuro? – zsharp
ha detto più veloce, non più sicuro, anche se sarei curioso di vedere come un confronto tra stringhe senza distinzione tra maiuscole e minuscole potrebbe utilizzare un confronto tra puntatori. –
La parola chiave "non sicura" non è necessariamente pericolosa da usare, ma ti consente di utilizzare i puntatori di memoria come faresti in C++. Molte funzioni nel framework .Net sono implementate in questo modo. Quindi entrambi i modi sono ugualmente sicuri da usare :) Ho semplicemente riferisco alla funzione effettiva nel quadro - private static int non sicuro CompareOrdinalIgnoreCaseHelper (string Stra stringa STRB) –
Un confronto GUID è un memcmp di 16 byte. Non sarà necessariamente peggio di un confronto tra stringhe, ma se ti preoccupi delle prestazioni tanto non dovresti usare il codice gestito.
Il confronto tra stringhe non fa distinzione tra maiuscole e minuscole. Mentre il confronto non dovrebbe essere molto diverso in termini di tempo, non è un confronto byte per byte come sarebbe un Guid. –
Non lo è. Il .Net guid consiste di Int32 + Int16 + Int16 + (byte * 8). E confronta uno contro l'altro fino all'ultimo byte. Significa un massimo di 11 confronti. –
Il codice gestito è in realtà piuttosto veloce - circa il 25-50% più lento di C++ l'ultima volta che ho controllato, circa lo stesso di Java ... confronta quello con l'8.000% più lento per Python/Ruby e il 50.000% più lento per PHP ... –
Nel mio test eseguendo un confronto UUID-UUID diretto confronto VS String-String, il confronto UUID richiede circa 1/4 del tempo come confronto di String.
Tuttavia, il casting di String-> UUID è costoso. Molto più costoso della conversione UUID-> String. Entrambi sono più costosi di entrambi i metodi di confronto.
Quindi: Se due UUID confrontano direttamente gli UUID. Se hai due stringhe, confronta le stringhe direttamente. Se si dispone di una stringa e un UUID, convertire l'UUID in una stringa e confrontare le stringhe.
.NET Guid è una struttura a 16 byte che, quando rappresentata come una stringa, verrà formattata in questo modello "xxxxxxxx-xxxx- xxxx-xxxx-xxxxxxxxxxxx "che è di circa 32 caratteri.
Così rappresentato come un GUID ci vorrebbe 16 byte e rappresentato come una stringa ci vorrebbe 32 * 2 = 64 byte.
Quindi GUID.Equals() dovrebbe funzionare meglio.
Anche GUID.Equals (GUID) funzionerebbe meglio di guid1 == guid2 perché non ci sono boxe coinvolti nel primo.
'Guid.Equals (oggetto, oggetto)' così avrai coinvolto un/boxing; per favore, vedi il mio benchmark lassù –
Guid.Equals (Guid) è descritto qui. http://msdn.microsoft.com/en-us/library/asw89aw8.aspx. Sembra che non ci siano boxe coinvolti per questo sovraccarico. – Santhosh
oh scusa, pensavo che stavi parlando della versione statica; ma, comunque, dovrai usare Guid.Equals (oggetto) mentre il punto intero riguarda il casting dall'oggetto –
non è abbastanza facile da testare? –
simile (ma non la stessa) domanda qui http://stackoverflow.com/questions/713109/performance-using-guid-object-or-guid-string-as-key –
Quando, mai, sarebbe importante? Sembra un caso di micro-ottimizzazione, che dovrebbe essere evitato a tutti i costi. Ricorda, prima fallo funzionare, che (se necessario) rendilo più veloce. –