13

我已经阅读了很多关于每种方法的优缺点的信息,并且我知道代表通常是针对一个听众的,而通知是针对许多听众的。问题是关于性能的。

我读过这个:NSNotificationCenter 与委派(使用协议)?

我正在通过通知将音频信号从麦克风发送到另一个班级。我知道我应该在这里使用委托,但我的问题是:委托会更快吗?因为我可以看到我有一些帧速率问题(降低),我想知道原因是否可能是使用通知而不是委托,或者没有关系?

4

7 回答 7

30

对于那些对性能感兴趣的人,我使用 XCTest 框架的measureBlockAPI 快速运行了一个简单的测试。简短的回答是,如果在循环中调用,差异将很大。

这是用于测试的代码:

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 秒

我试过的一个糟糕的选择

其他考虑因素是 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 秒

于 2015-02-03T22:11:32.940 回答
8

委托的开销更少,因此执行速度更快。

但是,一般来说,您应该只在可能成为问题的地方查看性能主题。对于像发送通知和调用委托这样的一次性任务,这永远不会成为问题。但是,当您计划在循环中使用变量(取决于数据)执行这些操作时,或者对于您已获取或接收数据的许多数据对象,无法预测会有多少 - 这些情况是我会考虑性能优化。

于 2013-07-29T10:15:54.340 回答
5

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。- 请求总是在主线程中处理,无论它们是从哪个线程分派的。

于 2017-08-14T12:02:45.563 回答
1

代表更快。

录制时的帧速率问题不是由于代理或通知。这是因为您正在主线程上执行所有任务,这也会呈现 UI。

于 2013-07-29T10:26:00.427 回答
0

我知道我应该在这里使用委托,但我的问题是:委托会更快吗?

这很简单:尝试并分享结果!

1:1时的委托,点对点关系可以比1:m在任何系统中发布和订阅更快。

是不是更快很难回答,因为它取决于环境。当听众不是很多并且发布者不需要搜索很多听众时,应该是相似的性能,但是当一百万个订阅者并且需要搜索它时,则可能是延迟,帧率下降。

于 2013-07-29T10:15:04.517 回答
0

调用委托只是一个方法调用,但是当使用通知时,应该在幕后做更多的事情来传递你的通知。考虑到这一点 - 委托要快一些。

实时音频处理是一项复杂的任务,我倾向于认为委托的方法调用或发送通知比您的音频处理代码产生的开销要少得多。

更新

考虑到性能问题,您总是应该在尝试不同方法时进行测量。

于 2013-07-29T10:20:51.257 回答
0

委托会比通知更快,但也不一定是您需要的。对于音频,您可能应该首先测量。如果您需要在更新 UI 之前更快地执行某些操作,那么您应该考虑通过 GCD 调度或 NSOperation 将一些处理任务移动到另一个线程。

于 2013-07-29T10:42:52.573 回答