Domanda

ero debug un'applicazione multi-filettata e trovato la struttura interna di CRITICAL_SECTION. Ho trovato membro dati LockSemaphore di CRITICAL_SECTION un interessante uno.

Sembra Critcal Section è un evento reset automatico (non un semaforo come suggerisce il nome) e il sistema operativo crea questo evento in silenzio quando prima volta un thread attende su Critical Section che è bloccato da qualche altro thread.

Ora, mi chiedo è sezione critica sempre più veloce? Event è un oggetto kernel e ogni oggetto sezione critica è associato ad oggetto evento allora come <=> può essere più veloce rispetto ad altri oggetti del kernel come Mutex? Inoltre, come fa oggetto evento interno in realtà colpisce le prestazioni della sezione critica?

Questa è la struttura del <=>:

struct RTL_CRITICAL_SECTION
{
    PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
    LONG LockCount;
    LONG RecursionCount;
    HANDLE OwningThread;
    HANDLE LockSemaphore;
    ULONG_PTR SpinCount;
};
È stato utile?

Soluzione

Quando si dice che una sezione critica è "veloce", significano "è a buon mercato per acquistare uno quando non è già bloccato da un altro filo".

[Si noti che, se è già bloccato da un altro thread, quindi non importa quasi tanto come veloce è.]

Il motivo per cui è veloce perché, prima di entrare nel kernel, utilizza l'equivalente di InterlockedIncrement su uno di quei LONG campo (magari sulla la LockCount campo) e in caso di successo, allora lo ritenga il blocco aquired senza essere andato nel kernel.

Il <=> API è penso implementata in modalità utente come un codice operativo "LOCK INC" ... in altre parole è possibile acquisire una sezione critica incontrastato senza fare alcuna transizione anello nel kernel a tutti.

Altri suggerimenti

Nel lavoro le prestazioni, alcune cose rientrano nella categoria "sempre" :) Se si implementa qualcosa di te stesso che è simile a una sezione critica OS utilizzando altre primitive allora le probabilità sono che sarà più lenta nella maggior parte dei casi.

Il modo migliore per rispondere alla tua domanda è con misurazioni delle prestazioni. Come oggetti OS eseguono è molto dipende lo scenario. Ad esempio, le sezioni critiche sono generali considerati 'veloce' se contesa è basso. Sono inoltre considerati veloce se il tempo di blocco è inferiore al tempo di conteggio di spin.

La cosa più importante per determinare se è contesa su una sezione critica è il primo ordine fattore limitante nell'applicazione. In caso contrario, è sufficiente utilizzare una sezione critica normalmente e lavorare sulle applicazioni principale collo di bottiglia (o collo).

Se le prestazioni sezione critica è critica, allora si può considerare il seguente.

  1. impostare con attenzione il conteggio spin lock per le sezioni critiche 'hot'. Se le prestazioni sono di primaria importanza, allora il lavoro qui è valsa la pena. Ricordate, mentre il blocco della rotazione fa evitare la modalità utente al kernel di transizione, che consuma tempo di CPU ad una velocità furiosa -, mentre la filatura, nient'altro arriva a usare questo tempo di CPU. Se un blocco viene mantenuto abbastanza a lungo, quindi il filo di filatura sarà blocco attuale, liberando che CPU a fare altri lavori.
  2. Se si dispone di un modello di lettore / scrittore quindi consigliabile utilizzare il Slim di lettura / scrittura (SRW) blocca . Il rovescio della medaglia è che qui sono disponibili solo su Vista e Windows Server 2008 e prodotti successivi.
  3. Si può essere in grado di utilizzare variabili di condizione con la sezione critica per ridurre al minimo il polling e contese, veglia discussioni solo quando necessario. Ancora una volta, questi sono supportati su Vista e Windows Server 2008 e prodotti successivi.
  4. interbloccate Liste a collegamento singolo ( SLIST) - questi sono efficienti e 'bloccare libero'. Ancora meglio, sono supportati su XP e Windows Server 2003 e prodotti successivi.
  5. Esaminare il codice -. Si può essere in grado di rompere una serratura 'hot' di refactoring del codice e l'utilizzo di un'operazione di bloccaggio o SLIST per la sincronizzazione e la comunicazione

In sintesi - scenari di ottimizzazione che hanno contesa dei blocchi può essere impegnativo (ma interessante!) Lavoro. Focus su misura le prestazioni delle applicazioni e la comprensione in cui i percorsi sono calde. Gli strumenti xperf nel Kit di Windows strumento Performance è tuo amico qui :) abbiamo appena rilasciato la versione 4.5 in Microsoft Windows SDK per Windows 7 e .NET Framework 3.5 SP1 ( ISO è qui , installer web qui ). È possibile trovare il forum per gli strumenti xperf qui . V4.5 supporta pienamente Win7, Vista, Windows Server 2008 -. Tutte le versioni

CriticalSections è più veloce, ma InterlockedIncrement / InterlockedDecrement è più. Vedere questa implementazione esempio dell'uso LightweightLock copia completa .

I CriticalSections gireranno un breve periodo (alcuni ms) e continuare a controllare se il blocco è libero. Dopo lo spin contare 'volte fuori', sarà poi ripiegare all'evento kernel. Quindi, nel caso in cui il titolare della serratura esce in fretta, non devi mai fare la transizione costosa al kernel codice.

EDIT: andarono e trovarono alcuni commenti nel mio codice: a quanto pare il MS Heap Manager utilizza un conteggio di rotazione di 4000 (incrementi interi, non ms)

Ecco un modo di vedere le cose:

Se non c'è conflitto, poi il blocco di spin è veramente veloce rispetto ad andare modalità kernel per un mutex.

Quando c'è contesa, un CriticalSection è leggermente più costoso che usare un mutex direttamente (a causa del lavoro extra per rilevare lo stato spinlock).

Quindi tutto si riduce ad una media ponderata, dove i pesi dipendono dalle specifiche della vostra configurazione delle chiamate. Detto questo, se avete poco contesa, poi un CriticalSection è grande vittoria. Se, d'altra parte, si ha sempre un sacco di contesa, allora si sarebbe pagando una piccola penalità sopra utilizzando direttamente un mutex. Ma in questo caso, quello che ci si guadagna con il passaggio a un mutex è piccola, quindi si sarebbe probabilmente meglio a cercare di ridurre la contesa.

sezione critica è più veloce di mutex perché, perché sezione critica non è un oggetto del kernel. Questo fa parte della memoria globale del processo corrente. Mutex effettivamente risiede nel Kernel e creazione di oggetti mutext richiede un interruttore kernel tranne nel caso di sezione critica non. Anche se la sezione critica è veloce, ci sarà un interruttore kernel durante l'utilizzo di sezione critica quando le discussioni sono in corso allo stato di attesa. Questo perché scheduling filo avviene nel lato kernel.

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