可可触摸编程。 内循环中的KVO/KVC超级慢。 我怎样才能加快速度?

发布于 2024-07-27 00:57:30 字数 473 浏览 6 评论 0原文

我已经成为 KVO/KVC 的忠实粉丝。 我喜欢它让我的 MVC 架构保持干净的方式。 然而,当我在我正在设计的 3D 渲染应用程序的内部渲染循环中使用 KVO 时,我并不喜欢所遭受的巨大性能损失,其中对于每个观察对象(可能是数百个),消息将以每秒 60 次的速度触发。

加速 KVO 的技巧和窍门有哪些? 具体来说,我正在观察一个标量值 - 而不是一个对象 - 所以也许包装/展开正在杀死我。 设置和拆除观察

[foo addObserver:bar forKeyPath:@"fooKey" options:0 context:NULL];
[foo removeObserver:bar forKeyPath:@"fooKey"];

我还在内部循环中 。 也许我因此而受到打击。

我真的真的很想保留 KVO 为我提供的巨大灵活性。 有没有速度狂人可以帮忙?

干杯, 道格

I've become a huge fan of KVO/KVC. I love the way it keeps my MVC architecture clean. However I am not in love with the huge performance hit I incur when I use KVO within the inner rendering loop of the 3D rendering app I'm designing where messages will fire at 60 times per second for each object under observation - potentially hundreds.

What are the tips and tricks for speeding up KVO? Specifically, I am observing a scalar value - not an object - so perhaps the wrapping/unwrapping is killing me. I am also setting up and tearing down observation

[foo addObserver:bar forKeyPath:@"fooKey" options:0 context:NULL];
[foo removeObserver:bar forKeyPath:@"fooKey"];

within the inner loop. Perhaps I'm taking a hit for that.

I really, really, want to keep the huge flexibility KVO provides me. Any speed freaks out there who can lend a hand?

Cheers,
Doug

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

救赎№ 2024-08-03 00:57:30

Objective-C 的消息调度和其他功能经过调整,并且速度相当快,但它们仍然没有达到调整 C 在计算任务方面的潜力:

NSNumber *a = [NSNumber numberWithIntegerValue:(b.integerValue + c.integerValue)];

比以下慢得多:

NSInteger a = b + c;

并且没有人真正对 Objective-C 中的对象进行数学计算出于这个原因(好吧,语法很糟糕)。

Objective-C 的强大之处在于,您拥有一个基于良好表达性消息的对象系统,您可以在需要时丢弃昂贵的位并使用纯 C。 KVO 是最昂贵的位之一。 我喜欢 KVO,我一直在使用它。 它的计算成本很高,尤其是当您有大量观察对象时。

内部循环是您一遍又一遍地运行的一小段代码,其中的任何事情都会一遍又一遍地完成。 如果需要,您应该在此处消除 OOP 功能,不应在此处分配内存,应考虑用静态内联函数替换方法调用。 即使您以某种方式设法在渲染循环中获得可接受的性能,它的性能也会比您从那里获得所有昂贵的通知和分派逻辑要低得多。

如果您确实想尝试使用 KVO 继续进行下去,您可以尝试执行以下几项操作来加快速度:

  1. 在对象中从自动 KVO 切换为手动 KVO。 这可以让您减少虚假通知
  2. 聚合更新:如果某个时间间隔内的中间值不相关,并且您可以推迟一段时间(例如下一个动画帧),则不要发布更改,请标记该更改需要发布并等待相关计时器关闭,您可能会避免一堆短暂的中间更新。 您还可以使用某种代理来聚合多个对象之间的相关更改。
  3. 合并可观察的属性:如果一种类型的对象中有大量可能会更改的属性,那么最好进行单个“hasChanges”属性观察并让观察者查询属性。

Objective-C's message dispatch and other features are tuned and pretty fast for what they provide, but they still don't approach the potential of tuned C for computational tasks:

NSNumber *a = [NSNumber numberWithIntegerValue:(b.integerValue + c.integerValue)];

is way slower than:

NSInteger a = b + c;

and nobody actually does math on objects in Objective-C for that reason (well that and the syntax is awful).

The power of Objective-C is that you have a nice expressive message based object system where you can throw away the expensive bits and use pure C when you need to. KVO is one of the expensive bits. I love KVO, I use it all the time. It is computationally expensive, especially when you have lots of observed objects.

An inner loop is that small bit of code you run over and over, anything thing there will be done over and over. It is the place where you should be eliminating OOP features if need be, where you should not be allocating memory, where you should be considering replacing method calls with static inline functions. Even if you somehow manage to get acceptable performance in your rendering loop, it will be much lower performance than if you got all that expensive notification and dispatch logic out of there.

If you really want to try to keep it going with KVO here are a few things you can try to make things go faster:

  1. Switch from automatic to manual KVO in your objects. This may allow you to reduce spurious notifications
  2. Aggregate updates: If your intermediate values over some time interval are not relevant, and you can defer for some amount of time (like the next animation frame) don't post the change, mark that the change needs to posted and wait for a the relevent timer to go off, you might get to avoid a bunch of short lived intermediary updates. You might also use some sort of proxy to aggregate related changes between multiple objects.
  3. Merge observable properties: If you have a large number of properties in one type of object that might change you may be better off making a single "hasChanges" property observe and having the the observer query the properties.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文