Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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 секунд

A Crappy Alternative я Пробовал

Другие соображения состоят в том, что производительность NSNotificationCenter, очевидно, может варьироваться в зависимости от количества слушателей для данного события и производительности кода, выполняемого этими слушателями. Также стоит отметить, что NSNotificationCenter синхронно вызывает слушателей уведомлений и в том же потоке, на который был вызван postNotification, который может быть получен при первом приближении к 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 секунд

Ответ 3

Делегаты работают быстрее.

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

Ответ 4

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

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

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

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

Ответ 5

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

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

UPDATE

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

Ответ 6

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

Ответ 7

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

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

Method call: .036 ms
Notification: .13 ms

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

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

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

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

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

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