2015-02-06 9 views
5

Ho seguente codice semplice:Ottenere statistica di prestazioni eseguite in C#

var tasks = statements.Select(statement => _session.ExecuteAsync(statement)); 
var result = Task.WhenAll(tasks).Result; 
[...] 

Come posso calcolare min, max, media, ecc di tutte le prestazioni eseguite? La classe attività non ha proprietà come "executionMilliseconds"

+2

Questo non è il compito di un'attività. Cosa ti impedisce di usare un cronometro, come spiegato in [Quanto tempo impiega il mio codice per funzionare?] (Http://stackoverflow.com/questions/1285052/how-long-does-my-code-take-to-run – CodeCaster

+0

Ho provato ad usare il cronometro, ma non so come posso misurare ogni attività. –

+1

Quindi vuoi misurare _each_ task, non _all_ tasks? Quindi dovrai implementare un cronometro in ogni attività. – CodeCaster

risposta

3

Con il seguente metodo di estensione:

public static class EnumerableExtensions 
{ 
    public static IEnumerable<Task<TimedResult<TReturn>>> TimedSelect<TSource, TReturn>(
     this IEnumerable<TSource> source, 
     Func<TSource, Task<TReturn>> func) 
    { 
     if (source == null) throw new ArgumentNullException("source"); 
     if (func == null) throw new ArgumentNullException("func"); 

     return source.Select(x => 
     { 
      Stopwatch stopwatch = new Stopwatch(); 
      stopwatch.Start(); 

      Task<TReturn> task = func(x); 

      Task<TimedResult<TReturn>> timedResultTask = task 
       .ContinueWith(y => 
       { 
        stopwatch.Stop(); 

        return new TimedResult<TReturn>(task, stopwatch.Elapsed); 
       }); 

      return timedResultTask; 
     }); 
    } 
} 

public class TimedResult<T> 
{ 
    internal TimedResult(Task<T> task, TimeSpan duration) 
    { 
     Task = task; 
     Duration = duration; 
    } 

    public readonly Task<T> Task; 
    public readonly TimeSpan Duration; 
} 

E callsite

var tasks = statements.TimedSelect(statement => _session.ExecuteAsync(statement)); 

var result = Task.WhenAll(tasks).Result; 

È possibile estrarre i risultati che avrete bisogno

// Whatever works (ugly, but just as an example)... 
var min = result.Select(x => x.Duration).Min(); 
var max = result.Select(x => x.Duration).Max(); 
var avg = new TimeSpan((long)result.Select(x => x.Duration.Ticks).Average()); 

Si noti che questo include piscina tempo di attesa (tempo in attesa che un thread di attività diventi disponibile) e quindi potrebbe non essere accurato.

Una variante non generica di questa estensione è un esercizio per il lettore.

+0

La tua versione precedente con il metodo 'Timed' era migliore, perché consente' _sessione.ExecuteAsync (istruzione) 'non è di tipo di elementi nell'array' statement' –

+0

Se si modifica la riga in definizione di funzione 'public IEnumerable >> TimedSelect (questa sorgente IEnumerable , Func > func)' sarà meglio –

+0

Ho trovato 'TimedSelect' migliore, perché il cronometro si avvia prima dell'inizio dell'attività. Quello con le catene "Timed" dopo l'avvio dell'attività e potrebbe determinare orari errati./Modifica: aggiornato, grazie. – Caramiriel

2

È possibile assegnare un numero di attività a ContinuationTask, che viene chiamato dopo il completamento dell'attività. Con questo puoi usare una serie di cronometri e usare l'attività di continuazione per fermarli individualmente.

+0

Come posso condividere il cronometro nell'attività di base e ContinuationTask? –

+0

Puoi mostrare un esempio di codice per favore? –

+0

Per evitare di alterare le attività, avrei un cronometro [], spegnerli tutti e quindi fermare l'ennesimo cronometro nell'ennesimo compito. Però. SInce Task.WaitAll() non fornisce alcuna garanzia circa l'avvio delle tue attività in un modo "equo", queste metriche ti diranno quando terminano le attività piuttosto che in senso stretto per quanto tempo hanno impiegato per l'esecuzione. Come punto generale, i thread di esecuzione sono una risorsa condivisa, quindi non è possibile gestire le cose in modo concorrente simultaneamente. –