Некоторое время в моей компании мы использовали доморощенную реализацию ObjectPool<T>
, которая обеспечивает блокировку доступа к ее содержимому.Это довольно просто: Queue<T>
, object
для блокировки и AutoResetEvent
для сигнализации «заимствованному» потоку при добавлении элемента.
Мясо класса действительно таководва метода:
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();
}
Мы использовали этот и несколько других классов коллекций вместо тех, которые предоставлены System.Collections.Concurrent
, потому что мы используем .NET 3.5, а не 4.0.Но недавно мы обнаружили, что, поскольку мы используем Reactive Extensions , на самом деле do имеет доступное нам пространство имен Concurrent
(в System.Threading.dll).
Естественно, я решил, что, поскольку BlockingCollection<T>
является одним из базовых классов в пространстве имен Concurrent
, он, вероятно, будет предлагать лучшую производительность, чем все, что я или мои товарищи по команде написали.
ИтакЯ попытался написать новую реализацию, которая работает очень просто:
public T Borrow() {
return _blockingCollection.Take();
}
public void Return(T obj) {
_blockingCollection.Add(obj);
}
К моему удивлению, согласно некоторым простым тестам (заимствование / возврат в пул несколько тысяч раз из нескольких потоков), наша первоначальная реализация значительно превосходит BlockingCollection<T>
с точки зрения производительности .Похоже, они оба работают правильно ;просто наша первоначальная реализация выглядит намного быстрее.
Мой вопрос:
- С чего бы это?Возможно, это связано с тем, что
BlockingCollection<T>
обеспечивает большую гибкость (насколько я понимаю, он работает, оборачивая IProducerConsumerCollection<T>
), что обязательно приводит к снижению производительности? - Это просто неуместное неправильное использованиекласса
BlockingCollection<T>
? - Если это правильное использование
BlockingCollection<T>
, я просто не правильно использую?Например, является ли Take
/ Add
подход слишком упрощенным, и есть гораздо более эффективный способ получить ту же функциональность?
Разве у кого-то есть что-то, что можно предложить в ответ на это?Третий вопрос. Похоже, что сейчас мы будем придерживаться нашей первоначальной реализации.