Desempenho de BlockingCollection (T)

Por um tempo, na minha empresa, usamos umObjectPool<T> implementação que fornece acesso bloqueador ao seu conteúdo. É bem direto: umQueue<T>, aobject travar e umAutoResetEvent para sinalizar para um segmento "emprestado" quando um item é adicionado.

A carne da classe é realmente esses dois métodos:

public T Borrow() {
    lock (_queueLock) {
        if (_queue.Count > 0)
            return _queue.Dequeue();
    }

    _objectAvailableEvent.WaitOne();

    return Borrow();
}

public void Return(T obj) {
    lock (_queueLock) {
        _queue.Enqueue(obj);
    }

    _objectAvailableEvent.Set();
}

Temos usado essa e algumas outras classes de coleção, em vez daquelas fornecidas porSystem.Collections.Concurrent porque estamos usando o .NET 3.5, não o 4.0. Mas recentemente descobrimos que, já que estamos usandoExtensões Reativasnós realmenteFaz tenha oConcurrent namespace disponível para nós (em System.Threading.dll).

Naturalmente, achei que desdeBlockingCollection<T> é uma das classes principais noConcurrent namespace, provavelmente ofereceria melhor desempenho do que qualquer coisa que eu ou meus colegas de equipe escrevêssemos.

Então, eu tentei escrever uma nova implementação que funciona de maneira muito simples:

public T Borrow() {
    return _blockingCollection.Take();
}

public void Return(T obj) {
    _blockingCollection.Add(obj);
}

Para minha surpresa, de acordo com alguns testes simples (emprestando / retornando ao pool alguns milhares de vezes de vários threads), nossa implementação originalbate significativamenteBlockingCollection<T> em termos de desempenho. Ambos parecem funcionarcorretamente; é que nossa implementação original parece ser muito mais rápida.

Minha pergunta:

Por que isso seria? Talvez seja porqueBlockingCollection<T> oferece maior flexibilidade (eu entendo que funciona envolvendo umaIProducerConsumerCollection<T>), que necessariamente introduz uma sobrecarga de desempenho?Este é apenas um uso equivocado e direto doBlockingCollection<T> classe?Se este for um uso apropriado deBlockingCollection<T>, não estou usando corretamente? Por exemplo, é oTake/Add abordagem excessivamente simplista, e há uma maneira muito melhor de obter a mesma funcionalidade?

A menos que alguém tenha algum insight a oferecer em resposta a essa terceira pergunta, parece que continuaremos com nossa implementação original por enquanto.

questionAnswers(3)

yourAnswerToTheQuestion