So che le eccezioni hanno una penalizzazione delle prestazioni e che è generalmente più efficiente cercare di evitare le eccezioni piuttosto che abbandonare un grosso tentativo/aggirare tutto - ma per quanto riguarda il blocco di prova stesso ? Qual è il costo della semplice dichiarazione di un tentativo/cattura, anche se non genera mai un'eccezione?Costo delle prestazioni di "prova" in C#
risposta
Il costo delle prestazioni di prova è molto ridotto. Il costo maggiore della gestione delle eccezioni è ottenere la traccia dello stack e altri metadati, e questo è un costo che non viene pagato fino a quando non si deve effettivamente lanciare un'eccezione.
Ma questo può variare in base alla lingua e all'implementazione. Perché non scrivere un semplice ciclo in C# e crearlo da solo?
Sì. Try è effettivamente gratuito perché è fondamentalmente gestito da metadati che vengono realmente controllati solo quando l'eccezione viene effettivamente lanciata. –
Si consiglia di leggere su Structured Exception Handling. È l'implementazione di Windows delle eccezioni e utilizzata in .NET.
Un detto comune è che le eccezioni sono costosi quando sono catturati - non torta. Questo perché più della raccolta dei metadati delle eccezioni (come ottenere una traccia stack ecc.) Avviene solo sul lato try-catch (non sul lato del lancio).
Disattivare lo stack è in realtà piuttosto veloce: il CLR risalta lo stack di chiamate e si limita a prestare attenzione ai blocchi che trova; in nessun punto di un blocco try-finally puro il runtime tenta di "completare" un'eccezione (sono i metadati ecc.).
Da quello che ricordo, qualsiasi try-catch con filtri (come "catch (FooException) {}") è altrettanto costoso - anche se non fanno nulla con l'eccezione.
mi permetto di dire che un metodo (lo chiamano CatchesAndRethrows) con il seguente blocco:
try
{
ThrowsAnException();
}
catch
{
throw;
}
potrebbe comportare una passeggiata pila più veloce in un metodo - come ad esempio:
try
{
CatchesAndRethrows();
}
catch (Exception ex) // The runtime has already done most of the work.
{
// Some fancy logic
}
alcuni numeri:
With: 0.13905ms
Without: 0.096ms
Percent difference: 144%
Ecco il punto di riferimento mi sono imbattuto (ricordate, modalità di rilascio - correre senza deb ug):
static void Main(string[] args)
{
Stopwatch withCatch = new Stopwatch();
Stopwatch withoutCatch = new Stopwatch();
int iterations = 20000;
for (int i = 0; i < iterations; i++)
{
if (i % 100 == 0)
{
Console.Write("{0}%", 100 * i/iterations);
Console.CursorLeft = 0;
Console.CursorTop = 0;
}
CatchIt(withCatch, withoutCatch);
}
Console.WriteLine("With: {0}ms", ((float)(withCatch.ElapsedMilliseconds))/iterations);
Console.WriteLine("Without: {0}ms", ((float)(withoutCatch.ElapsedMilliseconds))/iterations);
Console.WriteLine("Percent difference: {0}%", 100 * withCatch.ElapsedMilliseconds/withoutCatch.ElapsedMilliseconds);
Console.ReadKey(true);
}
static void CatchIt(Stopwatch withCatch, Stopwatch withoutCatch)
{
withCatch.Start();
try
{
FinallyIt(withoutCatch);
}
catch
{
}
withCatch.Stop();
}
static void FinallyIt(Stopwatch withoutCatch)
{
try
{
withoutCatch.Start();
ThrowIt(withoutCatch);
}
finally
{
withoutCatch.Stop();
}
}
private static void ThrowIt(Stopwatch withoutCatch)
{
throw new NotImplementedException();
}
Penso che l'OP abbia chiesto l'impatto sulle prestazioni quando NON sono state lanciate eccezioni. – Shimmy
In realtà, un paio di mesi fa mi è stato la creazione di una web app ASP.NET, e per sbaglio ho avvolto un blocco try/catch con un lunghissimo ciclo. Anche se il ciclo non generava eccezioni, ci voleva troppo tempo per finire. Quando sono tornato indietro e ho visto il try/catch avvolto dal loop, l'ho fatto al contrario, ho avvolto il loop nel blocco try/catch. Le prestazioni sono migliorate MOLTO. Puoi provarlo da solo: fai qualcosa come
int total;
DateTime startTime = DateTime.Now;
for(int i = 0; i < 20000; i++)
{
try
{
total += i;
}
catch
{
// nothing to catch;
}
}
Console.Write((DateTime.Now - startTime).ToString());
E poi prendi il blocco try/catch. Vedrai una grande differenza!
Hmmm. Ho appena provato questo. Net 2.0 (utilizzando un 'Cronometro'). 50000 tentativi di 20000 iterazioni di loop impiegano 4184 ms senza 'try-catch', 4363ms con' try-catch'. Questa è una differenza incredibilmente piccola. Tale differenza sarà ancora meno visibile se ogni iterazione sta effettivamente facendo qualcosa oltre una semplice operazione di addizione. Colpisco risultati simili con e senza debugging. – Brian
Per vedere quanto costa, è possibile eseguire il codice di seguito. Prende un semplice array bidimensionale e genera coordinate casuali che non rientrano nell'intervallo. Se la tua eccezione si verifica solo una volta, ovviamente non te ne accorgi. Il mio esempio è fatto per enfatizzare cosa significherà farlo parecchie migliaia di volte, e ciò che cattura un'eccezione rispetto all'implementazione di un semplice test ti salverà.
const int size = 1000;
const int maxSteps = 100000;
var randomSeed = (int)(DateTime.UtcNow - new DateTime(1970,1,1,0,0,0).ToLocalTime()).TotalMilliseconds;
var random = new Random(randomSeed);
var numOutOfRange = 0;
var grid = new int[size,size];
var stopwatch = new Stopwatch();
Console.WriteLine("---Start test with exception---");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < maxSteps; i++)
{
int coord = random.Next(0, size * 2);
try
{
grid[coord, coord] = 1;
}
catch (IndexOutOfRangeException)
{
numOutOfRange++;
}
}
stopwatch.Stop();
Console.WriteLine("Time used: " + stopwatch.ElapsedMilliseconds + "ms, Number out of range: " + numOutOfRange);
Console.WriteLine("---End test with exception---");
random = new Random(randomSeed);
stopwatch.Reset();
Console.WriteLine("---Start test without exception---");
numOutOfRange = 0;
stopwatch.Start();
for (int i = 0; i < maxSteps; i++)
{
int coord = random.Next(0, size * 2);
if (coord >= grid.GetLength(0) || coord >= grid.GetLength(1))
{
numOutOfRange++;
continue;
}
grid[coord, coord] = 1;
}
stopwatch.Stop();
Console.WriteLine("Time used: " + stopwatch.ElapsedMilliseconds + "ms, Number out of range: " + numOutOfRange);
Console.WriteLine("---End test without exception---");
Console.ReadLine();
uscita Esempio di questo codice:
---Start test with exception---
Time used: 3228ms, Number out of range: 49795
---End test with exception---
---Start test without exception---
Time used: 3ms, Number out of range: 49795
---End test without exception---
- 1. Costo delle prestazioni di un Memcopy in C/C++
- 2. Costo delle prestazioni dei confronti di tipo
- 3. Costo delle prestazioni del proxy dinamico Java
- 4. Costo delle prestazioni dell'utilizzo della digitazione dinamica in .NET
- 5. Come evitare il costo delle prestazioni di overflow: nascosto?
- 6. Costo delle prestazioni della creazione di ObjectContext in tutti i metodi in Entity Framework v1
- 7. overhead delle prestazioni delle variabili di typecasting in C
- 8. Costo delle prestazioni dei costrutti di threading: ottimizzazioni perse e allocazione di memoria
- 9. Ottimizzazione delle prestazioni SHA256 in C
- 10. costo delle funzioni lista in Python
- 11. Utilità di test delle prestazioni per C++
- 12. Il costo delle eccezioni C++ e setjmp/longjmp
- 13. Il costo delle prestazioni della codifica "sviluppo basato su eccezioni" in Java?
- 14. Esiste un costo delle prestazioni per l'autoboxing di un primitivo letterale?
- 15. Il costo delle prestazioni per utilizzare ref invece di restituire gli stessi tipi?
- 16. Test automatico delle prestazioni delle librerie Scala
- 17. C# Risorse di prova
- 18. Costo delle operazioni mobili della CPU
- 19. reinterpret_cast costo del cast
- 20. Costo dei gestori di eccezioni in Python
- 21. Come posso testare l'ottimizzazione delle prestazioni dell'unità in C#?
- 22. Accesso in C#: acquisizione delle prestazioni nome classe/metodo
- 23. C++: Miglioramento delle prestazioni della cache in un array 3d
- 24. prestazioni di size_t in C++
- 25. Strana differenza di prestazioni in C++?
- 26. Sovraccarico delle prestazioni di grandi dimensioni classe C#
- 27. Prestazioni di serializzazione C++
- 28. Il costo di thread_local
- 29. Qual è il costo dell'utilizzo di eccezioni in Objective-C?
- 30. Costo del messaggio di spedizione in Objective-C
Tu sei l'unica persona che può rispondere a questa domanda. Sei l'unica persona che sa che tipo di hardware e software stai utilizzando, sei l'unica persona che sa quali metriche di rendimento sono rilevanti per il tuo cliente e così via. Scrivi alcuni benchmark realistici, provali su hardware realistico e poi saprai la risposta. Chiunque cerchi di rispondere alla domanda per te sta indovinando o descrivendo le caratteristiche delle prestazioni sulle loro macchine, per i loro clienti, non per i tuoi. Ad ogni modo, non sono i dati che ti servono. –
@Eric - Ben detto. –