iPhone 4 上每秒可以发送多少条 Objective-C 消息?
当在尝试保持可重用性和分离模式的同时实现算法和其他事物时,我经常陷入这样的情况:
我在遍历大对象图时与委托来回通信。我担心的是所有这些消息传递会造成多大的伤害,或者我必须在多大程度上关心 Objective-C 消息传递开销。
另一种方法是不分离任何东西,并始终将单独的代码直接放入算法中,例如这个图形遍历器。但这在以后维护起来会很麻烦并且不可重用。
所以:只是为了了解一下它到底有多糟糕:在 iPhone 4 上一秒钟可以发送多少个 Objective-C 消息?
当然,我可以编写一个测试,但我不想让每条消息都增加一个变量,从而使其产生偏差。
When implementing algorithms and other things while trying to maintain reusability and separation patterns, I regularly get stuck in situations like this:
I communicate back and forth with an delegate while traversing a big graph of objects. My concern is how much all this messaging hurts, or how much I must care about Objective-C messaging overhead.
The alternative is to not separate anything and always put the individual code right into the algorithm like for example this graph traverser. But this would be nasty to maintain later and is not reusable.
So: Just to get an idea of how bad it really is: How many Objective-C messages can be sent in one second, on an iPhone 4?
Sure I could write a test but I don't want to get it biased by making every message increment a variable.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
确实没有一个恒定的数字。如果手机在后台检查电子邮件,或者您有一个后台线程在执行 IO 工作,该怎么办?
处理此类事情的方法是,先做简单的事情。按照您的意愿致电代表,看看表现是否正常。
如果不是,那么就想办法改进。如果消息传递是开销,您可以将其替换为计划 C 函数调用。
There's not really a constant number to be had. What if the phone is checking email in the background, or you have a background thread doing IO work?
The approach to take with things like this is, just do the simple thing first. Call delegates as you would, and see if performance is OK.
If it's not, then figure out how to improve things. If messaging is the overhead you could replace it with a plan C function call.
隐含地把这个问题理解为“你在什么时候会为了速度而牺牲良好的设计模式?”,我会补充说,你可以消除许多 Objective-C 成本,同时保留大部分的好处好的设计。
Objective-C 的动态分派会查阅某种类型的表,以将 Objective-C 选择器映射到这些方法的 C 级实现。然后,它执行C函数调用,或者返回到备份机制之一(例如,转发目标)和/或如果不存在这样的调用则最终抛出异常。在您已经有效地得到:(
这是荒谬的人为,但您明白了这一点)的情况下,您可以执行:
您所做的就是采取调度的动态部分 - C 函数查找 - 在内部外部环形。所以你失去了许多动态的好处。 “delegate”无法在循环期间进行 swizzle 方法,其副作用是您可能会破坏键值观察,并且所有备份机制都将不起作用。但你已经成功地将动态的东西从循环中拉出来。
由于它很丑陋并且破坏了许多 Objective-C 机制,因此我认为在一般情况下这种做法是不好的。我建议的主要地方是当你有一个或一组严格约束的类隐藏在外观模式后面的某个地方时(因此,你提前确切地知道谁将与谁通信以及在什么情况下通信)并且你能够明确证明动态调度会让您付出巨大的代价。
有关 C 级别内部工作原理的完整详细信息,请参阅 Objective-C 运行时参考。然后,您可以对照 NSObject 类参考< /a> 查看哪里提供了获取一些信息的便捷方法(例如我在示例中使用的 IMP)。
Taking the question implicitly to be "at what point do you sacrifice good design patterns for speed?", I'll add that you can eliminate many of the Objective-C costs while keeping most of the benefits of good design.
Objective-C's dynamic dispatch consults a table of some sort to map Objective-C selectors to the C-level implementations of those methods. It then performs the C function call, or drops back onto one of the backup mechanisms (eg, forwarding targets) and/or ends up throwing an exception if no such call exists. In situations where you've effectively got:
(which is ridiculously artificial, but you get the point), you can instead perform:
What you've done there is taken the dynamic part of the dispatch — the C function lookup — outside the inner loop. So you've lost many dynamic benefits. 'delegate' can't method swizzle during the loop, with the side effect that you've potentially broken key-value observing, and all of the backup mechanisms won't work. But what you've managed to do is pull the dynamic stuff out of the loop.
Since it's ugly and defeats many of the Objective-C mechanisms, I'd consider this bad practice in the general case. The main place I'd recommend it is when you have a tightly constrained class or set of classes hidden somewhere behind the facade pattern (so, you know in advance exactly who will communicate with whom and under what circumstances) and you're able to prove definitively that dynamic dispatch is costing you significantly.
For full details of the inner workings at the C level, see the Objective-C Runtime Reference. You can then cross-check that against the NSObject class reference to see where convenience methods are provided for getting some bits of information (such as the IMP I use in the example).