Domanda

    

Questa domanda ha già una risposta qui:

         

Sto cercando un modo per confrontare le chiamate dei metodi in C #.

Ho codificato una struttura di dati per i compiti universitari e ho appena trovato un modo per ottimizzare un po ', ma in un modo che aggiungerebbe un po' di sovraccarico in tutte le situazioni, trasformando una chiamata O (n) in O (1) in alcuni.

Ora voglio eseguire entrambe le versioni con i dati del test per vedere se vale la pena implementare l'ottimizzazione. So che in Ruby, potresti racchiudere il codice in un blocco Benchmark e avere il tempo necessario per eseguire il blocco in console - c'è qualcosa di simile disponibile per C #?

È stato utile?

Soluzione

Puoi utilizzare la classe cronometro incorporata " Fornisce una serie di metodi e proprietà che puoi utilizzare per misurare accuratamente il tempo trascorso. " se stai cercando un modo manuale per farlo. Non sono sicuro di automatizzato però.

Altri suggerimenti

Rubato (e modificato) dalla risposta di Yuriy:

private static void Benchmark(Action act, int iterations)
{
    GC.Collect();
    act.Invoke(); // run once outside of loop to avoid initialization costs
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < iterations; i++)
    {
        act.Invoke();
    }
    sw.Stop();
    Console.WriteLine((sw.ElapsedMilliseconds / iterations).ToString());
}

Spesso un metodo particolare deve inizializzare alcune cose e non sempre si desidera includere tali costi di inizializzazione nel benchmark generale. Inoltre, si desidera dividere il tempo di esecuzione totale per il numero di iterazioni, in modo che la stima sia più o meno indipendente dal numero di iterazioni.

Ho rubato la maggior parte di quanto segue dal metodo di benchmarking di Jon Skeet:

private static void Benchmark(Action act, int interval)
{
    GC.Collect();
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < interval; i++)
    {
        act.Invoke();
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

Ecco alcune cose che ho trovato per tentativi ed errori.

  1. Elimina il primo batch di (migliaia) iterazioni. Molto probabilmente saranno colpiti dal JITter.
  2. L'esecuzione del benchmark su un oggetto Thread separato può fornire risultati migliori e più stabili. Non so perché.
  3. Ho visto alcune persone usare Thread.Sleep per qualsiasi motivo prima di eseguire il benchmark. Questo non farà che peggiorare le cose. Non so perché. Forse a causa del JITter.
  4. Non eseguire mai il benchmark con il debug abilitato. Molto probabilmente il codice eseguirà ordini di grandezza più lenti.
  5. Compila la tua applicazione con tutte le ottimizzazioni abilitate. Alcuni codici possono essere drasticamente influenzati dall'ottimizzazione, mentre altri non lo saranno, quindi la compilazione senza ottimizzazione influirà sull'affidabilità del benchmark.
  6. Quando si compila con le ottimizzazioni abilitate, a volte è necessario in qualche modo valutare l'output del benchmark (ad es. stampare un valore, ecc.). Altrimenti il ??compilatore potrebbe "capire" che alcuni calcoli sono inutili e semplicemente non li eseguiranno.
  7. L'invocazione di delegati può avere un notevole sovraccarico quando si eseguono determinati benchmark. È meglio inserire più di una iterazione all'interno del delegato, in modo che l'overhead abbia scarso effetto sul risultato del benchmark.
  8. I profiler possono avere il proprio overhead. Sono bravi a dirti quali parti del tuo codice sono colli di bottiglia, ma non sono bravi a confrontare due cose diverse in modo affidabile.
  9. In generale, le fantasiose soluzioni di benchmarking possono avere notevoli spese generali. Ad esempio, se si desidera eseguire il benchmark di molti oggetti utilizzando un'unica interfaccia, potrebbe essere allettante avvolgere ogni oggetto in una classe. Tuttavia, ricorda che anche il costruttore della classe ha un sovraccarico che deve essere preso in considerazione. È meglio mantenere tutto il più semplice e diretto possibile.

Sembra che tu voglia un profiler . Consiglio vivamente il profiler EQATEC , essendo il migliore gratuito che abbia mai provato. La cosa bella di questo metodo rispetto a un semplice cronometro è che fornisce anche una suddivisione delle prestazioni su determinati metodi / blocchi.

I profiler offrono i migliori parametri di riferimento in quanto diagnosticano tutto il codice, tuttavia lo rallentano molto. I profilatori vengono utilizzati per trovare i colli di bottiglia.

Per ottimizzare un algoritmo, quando sai dove sono i colli di bottiglia, usa un dizionario di nomi - > cronometro, per tenere traccia delle sezioni critiche in termini di prestazioni durante il runtime.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top