ReaderWriterLockSlim vs. monitor
-
03-07-2019 - |
Pergunta
Eu tenho uma implementação IDictionary<TKey,TValue>
que mantém internamente n outra Dictionary<TKey, TValue>
e distribui que as inserções pelo HashCode da chave para as sub-dicionários invidual. Com 16 sub-dicionários, o número de colisões é bastante baixo em uma máquina de 4-núcleo.
Para inserções paralelas, i bloqueado o método Add com um ReaderWriterLockSlim
, bloqueio somente o indivíduo subdicionário:
public void Add(TKey key, TValue value)
{
int poolIndex = GetPoolIndex(key);
this.locks[poolIndex].EnterWriteLock();
try
{
this.pools[poolIndex].Add(key, value);
}
finally
{
this.locks[poolIndex].ExitWriteLock();
}
}
Ao inserir itens com quatro threads, eu só tenho sobre o uso da CPU de 32% e mau desempenho. Então eu substituiu o ReaderWriterLockSlim por um Monitor (isto é, a palavra-chave lock
).
uso da CPU estava agora em quase 100% eo desempenho foi mais do que duplicou.
A minha pergunta é: Por que o aumento de uso da CPU? O número de colisões não deve ter mudado. O que torna ReaderWriterLock.EnterWriteLock esperar tantas vezes?
Solução
Para escrever-somente carregar o Monitor é mais barato do que ReaderWriterLockSlim, no entanto, se você simular ler + carga write onde leitura é muito maior do que escrita, então ReaderWriterLockSlim deve se realizar Monitor.
Outras dicas
Eu não sou nenhum guru, mas meu palpite é que RWLS é mais voltados para a contenção pesado (por exemplo, centenas de tópicos), enquanto Monitor
está mais em sintonia para aquelas sincronização one-off questões.
Pessoalmente eu uso uma classe TimerLock
que usa o Monitor.TryEnter
com um parâmetro de tempo limite.
Como você sabe o que causou o mau desempenho? Você não pode ir supondo que, a única maneira é fazer algum tipo de profiling.
Como você lida com bloqueio para a recolha dos pais ou é constante?
Talvez você precisa adicionar alguns saída de depuração e ver o que realmente acontece?