BlockingCollection (T) производительность

Некоторое время в моей компании мы использовали собственной разработки ObjectPool реализация, которая обеспечивает блокирующий доступ к его содержанию. Это довольно просто: a Queue, 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. Но недавно мы обнаружили, что, так как мы используем Реактивные Расширения, мы на самом деле имеем Concurrent пространство имен, доступное нам (в System.Threading.dll).

Естественно, я полагал это с тех пор BlockingCollection один из базовых классов в Concurrent пространство имен, это, вероятно, предложило бы лучшую производительность, чем что-нибудь, что я или мои товарищи по команде записали.

Таким образом, я пытался писать новую реализацию, которая работает очень просто:

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

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

К моему удивлению, согласно некоторым простым тестам (одалживающий/возвращающий к пулу несколько тысяч раз от нескольких потоков), наша исходная реализация значительно бьется BlockingCollection с точки зрения производительности. Они оба, кажется, работают правильно; это просто, что наша исходная реализация, кажется, намного быстрее.

Мой вопрос:

  1. Почему это было бы? Это, возможно, потому что BlockingCollection предлагает большую гибкость (я понимаю, что она работает путем обертывания IProducerConsumerCollection), который обязательно представляет производительность наверху?
  2. Это просто утончение дезинформированного использования BlockingCollection класс?
  3. Если это - соответствующее использование BlockingCollection, разве я просто не использую правильно? Например, Take/Add чрезмерно упрощенный подход, и существует далекий лучше работающий способ получить ту же функциональность?

Если у любого нет некоторого понимания для предложения в ответ на тот третий вопрос, похоже, что мы будем придерживаться нашей исходной реализации на данный момент.

22
задан Dan Tao 14 June 2010 в 18:14
поделиться

1 ответ

Здесь есть несколько потенциальных возможностей.

Во-первых, BlockingCollection в Reactive Extensions - это резервный порт, а не совсем то же самое, что и в окончательной версии .NET 4. Я не удивлюсь, если производительность этого бэкпорта будет отличаться от .NET 4 RTM (хотя я специально не профилировал эту коллекцию). Большая часть TPL работает в .NET 4 лучше, чем в backport .NET 3.5.

При этом я подозреваю, что ваша реализация будет превосходить BlockingCollection , если у вас есть один поток-производитель и один поток-потребитель. С одним производителем и одним потребителем ваша блокировка будет иметь меньшее влияние на общую производительность, а событие сброса - очень эффективное средство ожидания на стороне потребителя.

Однако BlockingCollection разработан, чтобы позволить многим потокам-производителям очень хорошо «ставить в очередь» данные. Это не будет хорошо работать с вашей реализацией, так как конкуренция за блокировку довольно быстро начнет становиться проблематичной.

При этом я также хотел бы указать здесь на одно заблуждение:

... он, вероятно, будет предлагать лучшую производительность, чем все, что написано мной или моими товарищами по команде.

Это часто неправда. Классы коллекции каркаса обычно работают очень хорошо , но часто не являются наиболее производительным вариантом для данного сценария. При этом они, как правило, работают хорошо, будучи очень гибкими и надежными. Часто они очень хорошо масштабируются.«Самодельные» классы коллекций часто превосходят по эффективности коллекции каркаса в определенных сценариях, но имеют тенденцию вызывать проблемы при использовании в сценариях, отличных от того, для которого они были специально разработаны. Я подозреваю, что это одна из таких ситуаций.

26
ответ дан 29 November 2019 в 04:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: