BlockingCollection (T) Leistung

Für eine Weile in meiner Firma haben wir ein hausgemachtes verwendetObjectPool<T> Implementierung, die den Zugriff auf den Inhalt blockiert. Es ist ziemlich einfach: einQueue<T>, einobject zu sperren, und einAutoResetEvent, um einem "ausleihenden" Thread zu signalisieren, wenn ein Element hinzugefügt wird.

Das Fleisch der Klasse ist wirklich diese beiden Methoden:

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();
}

Wir haben diese und einige andere Sammlungsklassen anstelle der von @ bereitgestellten verwendeSystem.Collections.Concurrent weil wir .NET 3.5 verwenden, nicht 4.0. Aber vor kurzem haben wir festgestellt, dass wir @ verwend Reaktive Erweiterungen, wir eigentlichtu habe denConcurrent für uns verfügbarer Namespace (in System.Threading.dll).

Natürlich dachte ich, dass seitBlockingCollection<T> ist eine der Kernklassen imConcurrent Namespace, es würde wahrscheinlich eine bessere Leistung bieten als alles, was ich oder meine Teamkollegen geschrieben haben.

So habe ich versucht, eine neue Implementierung zu schreiben, die sehr einfach funktioniert:

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

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

To meine Überraschung, nach einigen einfachen Tests (Ausleihen / Zurückkehren in den Pool ein paar tausend Mal von mehreren Threads), unsere ursprüngliche Implementierungsignifikant schlägtBlockingCollection<T> in Bezug auf die Leistung. Sie scheinen beide zu arbeitenkorrek; Es ist nur so, dass unsere ursprüngliche Implementierung viel schneller zu sein scheint.

Meine Frage

Warum wäre das? Liegt es vielleicht daran, dassBlockingCollection<T> bietet größere Flexibilität (ich verstehe, dass es funktioniert, wenn einIProducerConsumerCollection<T>), was zwangsläufig einen Performance-Overhead mit sich bringt?Ist dies nur eine pauschale Fehlbedienung desBlockingCollection<T> Klasse?Wenn dies eine angemessene Verwendung von @ iBlockingCollection<T>, verwende ich es einfach nicht richtig? Ist zum Beispiel dasTake/Add Ansatz zu simpel, und es gibt einen viel leistungsstärkeren Weg, um die gleiche Funktionalität zu erhalten?

Wenn niemand einen Einblick in die Antwort auf diese dritte Frage hat, werden wir wohl vorerst an unserer ursprünglichen Implementierung festhalten.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage