2015-08-21 11 views
5

Per ogni chiamata emessa al server, creo un nuovo timer per Task.Delay per controllare il suo timeout.Come sono le prestazioni quando ci sono centinaia di Task.Delay

Diciamo che ci sarebbero centinaia di chiamate simultanee. Quindi ci sarebbero centinaia di Task contando il timer.

Immagino che l'implementazione interna di TPL abbia considerato questa occasione e tutte le attività si basano sullo stesso timer sottostante?

Non riesco a capire il meccanismo con cui il Task.Delay funziona internamente.

+0

AFAIK, tutte le attività utilizzano i thread allocati da un ThreadPool. Se si desidera garantire alcuni requisiti prestazionali personalizzati, è sempre possibile creare una TaskFactory personalizzata adatta alle proprie esigenze. – d3dave

+1

@ d3dave no non è affatto vero. Task.Delay utilizza i timer non i thread. TaskCompletionSource è un altro esempio di Attività senza thread. –

risposta

9

Task.Delay è implementato con un numero interno System.Threading.Timer. Quella classe di timer è un wrapper in cima a un singolo timer nativo. Per sincronizzare l'accesso a quel singolo timer nativo c'è un livello di blocco AppDomain sulla creazione di nuovi timer (e la modifica di quelli esistenti). Si può vedere che nel reference source:

internal bool Change(uint dueTime, uint period) 
{ 
    // ... 
    lock (TimerQueue.Instance) 
    { 
     // ... 
    } 
    // ... 
} 

Nella maggior parte dei casi va bene, ma quando si crea una notevole quantità di questi timer al secondo è possibile ottenere un grave contenzioso su quel blocco. L'unico modo per sapere in realtà è il profilo in un ambiente reale.


io, personalmente, hanno raggiunto quel punto con la creazione di auto-cancellazione di troppi CancellationTokenSource utilizzando i timer (si può vedere come ho evitato che sul mio blog: Surprising Contention In System.Threading.Timer).

C'è anche questo post di Stephen Toub su Coalescing CancellationTokens from Timeouts che cita:

"Certo, ci sono sempre gli scenari la spinta i confini delle prestazioni, e di recente abbiamo visto alcuni casi di alto throughput, la gente stava creando uno di questi CancellationToken per ciascuna delle migliaia e migliaia di chiamate asincrone effettuate al secondo. Si tratta di un sacco di istanze Timer e CancellationTokenSource ".

+1

Trovo sempre i blocchi globali nella sorpresa di BCL. Un altro è in ExceptionDispatchInfo. Aspetta il ridimensionamento della gestione delle eccezioni in attesa. – usr

+0

Il link per il tuo blog non è valido nella tua risposta. [Sorprendente contesa in System.Threading.Timer] (http://blog.i3arnon.com/2015/07/25/surprising-timer-contention/) – Absolom

+0

@Absolom ora riparato. Grazie per averlo precisato... – i3arnon