Question

I était le débogage d'une application multi-filetée et trouvé la structure interne de CRITICAL_SECTION. J'ai trouvé membre de données de CRITICAL_SECTION un LockSemaphore d'intéressant.

Il ressemble à un événement est Critcal Section réinitialisation automatique (pas sémaphores comme son nom l'indique) et le système d'exploitation crée cet événement en silence lors de la première fois qu'une thread attend sur ce qui est verrouillé Critical Section par un autre thread.

Maintenant, je me demande est toujours plus rapide Section critique? L'événement est un objet noyau et chaque objet section critique est associée à l'objet de l'événement alors comment peut être plus rapide <=> par rapport à d'autres objets du noyau comme Mutex? En outre, comment objet événement interne affecte réellement la performance de l'article critique?

Voici la structure du <=>:

struct RTL_CRITICAL_SECTION
{
    PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
    LONG LockCount;
    LONG RecursionCount;
    HANDLE OwningThread;
    HANDLE LockSemaphore;
    ULONG_PTR SpinCount;
};
Était-ce utile?

La solution

Quand ils disent qu'une section critique est « rapide », ils veulent dire «c'est pas cher d'acquérir une quand il est pas déjà verrouillé par un autre thread ».

[Notez que si est déjà verrouillé par un autre thread, il n'a pas d'importance presque tant la façon dont il est rapide.]

La raison pour laquelle il est rapide parce que, avant d'entrer dans le noyau, il utilise l'équivalent de l'un des InterlockedIncrement les champs LONG (peut-être sur le terrain du LockCount) et si elle réussit alors il considère le verrou aquired sans avoir entré dans le noyau.

L'API est <=> Je pense mis en œuvre en mode utilisateur comme « LOCK INC » opcode ... en d'autres termes, vous pouvez acquérir une section critique non contestée sans faire de transition anneau dans le noyau du tout.

Autres conseils

Dans le travail de performance, peu de choses tombent dans le « toujours » la catégorie :) Si vous implémentez quelque chose vous-même qui est semblable à une section critique OS à l'aide d'autres primitives alors les chances sont que ce sera plus lente dans la plupart des cas.

La meilleure façon de répondre à votre question est avec des mesures de performance. Comment les objets OS exécutent est très en fonction du scénario. Par exemple, les sections critiques sont en général considérés comme « rapide » si affirmation est faible. Ils sont également considérés comme rapide si le temps de verrouillage est inférieur au nombre de spin temps.

La chose la plus importante est de déterminer si la contention sur une section critique est le premier facteur limitant l'ordre dans votre application. Sinon, il suffit d'utiliser une section critique et travailler sur normaly vos applications goulot d'étranglement primaire (ou le cou).

Si la performance de section critique est critique, alors vous pouvez envisager ce qui suit.

  1. soigneusement définir le nombre de verrouillage de spin pour vos sections critiques « à chaud ». Si la performance est primordiale, le travail ici en vaut la peine. Rappelez-vous, alors que le verrou de rotation n'évite le mode utilisateur à la transition du noyau, il consomme du temps CPU à un rythme furieux - tout en faisant tourner, rien d'autre obtient d'utiliser ce temps CPU. Si un verrou est maintenu assez longtemps, puis le fil de filature bloquerons réelle, ce qui libère cette CPU pour faire d'autres travaux.
  2. Si vous avez un modèle de lecture / écriture alors envisager d'utiliser le Slim lecteur / graveur (SRW) verrouille . L'inconvénient ici est qu'ils ne sont disponibles que sur Vista et Windows Server 2008 et les produits plus tard.
  3. Vous pourrez peut-être utiliser avec votre section critique pour minimiser l'interrogation et la discorde, les discussions se réveiller uniquement en cas de besoin. Encore une fois, ceux-ci sont pris en charge sur Vista et Windows Server 2008 et les produits plus tard.
  4. Envisagez d'utiliser verrouillables Singly listes chaînées ( SLIST) - ceux-ci sont efficaces et « verrouiller libre ». Mieux encore, ils sont pris en charge sur XP et Windows Server 2003 et les produits ultérieurs.
  5. Examinez votre code -. Vous pourrez peut-être briser une serrure « à chaud » par refactorisation du code et en utilisant une opération interverrouillage ou SLIST pour la synchronisation et la communication

En résumé - scénarios de réglage qui ont la contention de verrouillage peut être difficile (mais intéressant!) Travail. Mettre l'accent sur la mesure de vos performances et la compréhension des applications où sont vos chemins chauds. Les outils Xperf dans le kit performances Windows outil est votre ami ici :) nous venons de publier la version 4.5 dans le SDK Microsoft Windows pour Windows 7 et .NET Framework 3.5 SP1 ( ISO est ici , installateur web ). Vous pouvez trouver le forum pour les outils Xperf . V4.5 soutient pleinement Win7, Vista, Windows Server 2008 -. Toutes les versions

CriticalSections est plus rapide, mais InterlockedIncrement / InterlockedDecrement est plus. Voir cet exemple l'utilisation mise en œuvre LightweightLock copie complète .

Les CriticalSections tourneront un peu de temps (quelques ms) et continuer à vérifier si le verrou est libre. Après le spin compte « fois sur », il sera alors revenir à l'événement du noyau. Ainsi, dans le cas où le titulaire de la serrure sort rapidement, vous ne devez jamais faire la transition coûteuse au code du noyau.

EDIT: Je suis allé et a trouvé quelques commentaires dans mon code: apparemment le MS Heap Manager utilise un nombre de rotation de 4000 (incréments entiers, pas ms)

Voici une façon de regarder:

S'il n'y a pas de conflit, le verrou de rotation très rapide par rapport à passer en mode noyau pour un Mutex.

Quand il y a conflit, un CriticalSection est un peu plus cher que d'utiliser un Mutex directement (en raison du travail supplémentaire pour détecter l'état spinlock).

Il se résume à une moyenne pondérée, les coefficients de pondération dépendent des spécificités de votre modèle d'appel. Cela étant dit, si vous avez peu de conflits, alors CriticalSection est grande victoire. Si, d'autre part, vous avez toujours beaucoup de discorde, alors vous payer une pénalité très faible sur l'aide d'un Mutex directement. Mais dans ce cas, ce que vous gagnez en passant à un Mutex est faible, de sorte que vous seriez probablement mieux essayer de réduire l'affirmation.

Section critique est plus rapide que mutex pourquoi parce que l'article critique n'est pas un objet du noyau. Cela fait partie de la mémoire globale du processus en cours. Mutex réside en fait dans le noyau et la création d'objet mutext nécessite un commutateur du noyau, mais en cas de section critique non. Même si la section critique est rapide, il y aura un commutateur du noyau tout en utilisant la section critique lorsque les discussions vont état d'attente. En effet, l'ordonnancement des threads se produit dans le côté du noyau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top