NSNotificationCenter vs делегирование-что быстрее?

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

Я прочитал это : NSNotificationCenter против делегирования (с использованием протоколов)?

Я посылаю звуковые сигналы от микрофона в другой класс по уведомлению . я знаю, что здесь я должен использовать делегата, но мой вопрос: делегаты будут быстрее ? потому что я вижу, я некоторая проблема частоты кадров (уменьшена), и я хотел бы знать, может ли причиной быть использование уведомления делегата, или нет никакого отношения ?

7 ответов


делегаты приходят с меньшими накладными расходами и поэтому будут выполняться намного быстрее.

однако в целом вы должны смотреть на темы производительности только там, где они, вероятно, будут проблемой вообще. Для одноразовых задач, таких как отправка уведомления или вызов делегата, это никогда не должно быть проблемой. Но когда вы планируете выполнять их в цикле с переменным (в зависимости от данных) количеством интараций или для ряда объектов данных, где вы получили или получили данные невозможно предсказать, сколько их будет - это ситуации, в которых я бы рассмотрел оптимизацию производительности.


для тех, кто заинтересован в производительности, я провел простой тест в swift, используя measureBlock API-интерфейс. Короткий ответ заключается в том, что при вызове в цикле разница будет значительной.

вот код, используемый для проверки:

public protocol MyTestClassDelegate: class {
    func myTestDelegateCallback()
}

public let TestClassValueChangedNotification = "TestClassNotification"

public class MyViewModel {
    public weak var delegate: MyTestClassDelegate?
    public init() { }
    public func doNotification() {
       NSNotificationCenter.defaultCenter().postNotificationName(TestClassValueChangedNotification, object: nil)
    }

    public func doDelegation(value: Int) {
        delegate?.myTestClassDelegateCallback()
    }
}

и тестовые примеры:

func testPerformanceNotifiction() {
   measureBlock { () -> Void in
       let testClass = MyTestClass()
       for i in 0...100000 {
          testClass.doNotification(i)
       }
   }
}

func testPerformanceDelegation() {
   measureBlock { () -> Void in
        let testClass = MyTestClass()
        testClass.delegate = self
        for i in 0...100000 {
            testClass.doDelegation(i)
        }
   }
}

результаты:
- делегация:- - - - - - 0.957 секунды
- Центр уведомлений: - 3.882 секунд

Дерьмовая Альтернатива I Пробовал

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

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

public func doMultipleDelegatation() {
    for i in 0..<delegates.count {
        delegates[i].myTestDelegateCallback()
    })
}

func testPerformanceMultipleDelegation() {
   measureBlock { () -> Void in
        let testClass = MyTestClass()
        testClass.delegates = [self]
        for i in 0...100000 {
            testClass.doMultipleDelegation(i)
        }
   }
}

Окончательные Результаты:
- делегация:- - - - - - 0.957 секунды
- Центр уведомлений: - 3.882 секунд
- множественное делегирование: - 6.488 секунд


делегаты быстрее.

ваша проблема частоты кадров во время записи не из-за делегатов или уведомлений. Это потому, что вы выполняете все свои задачи в основном потоке, который также отображает пользовательский интерфейс.


NotificationCenter работает достаточно быстро.

во-первых, я протестировал синхронный случай публикации и получения уведомления в основном потоке, сравнив его с вызовом метода на self:

Method call: .036 ms
Notification: .13 ms

каждый номер является худшим случаем среди 100 вызовов.

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

во-вторых, я разместил уведомление из фоновой очереди и получил его в главной очереди, сравнив его с DispatchQueue:

Notification: 877 ms
DispatchQueue.sync: 871 ms
DispatchQueue.async: 867 ms

здесь почти нет разницы.

методология: - Режим релиза - iPhone 5s - iOS 10.3.2. - Запросы всегда обрабатываются в основном потоке, независимо от того, из какого потока они отправляются.


Я знаю, что здесь я должен использовать делегат, но мой вопрос : делает делегаты будут быстрее ?

это легко: попробуйте поделиться результатами!

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

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


делегат будет быстрее, чем уведомление, но не обязательно то, что вам нужно. Для аудио вы, вероятно, должны сначала измерить. Если вам нужно что-то выполнить быстрее перед обновлением пользовательского интерфейса, вы должны посмотреть на перемещение некоторой задачи обработки в другой поток через GCD dispatch или NSOperation.


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

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

обновление

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