为什么在我的加速度计回调中使用 static int 比使用实例变量慢得多?

发布于 2024-08-12 13:53:14 字数 1394 浏览 2 评论 0原文

我正在研究 GLGravity 示例,以找出与处理加速度计相关的一些性能细微差别。

这是有问题的代码:

- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
    static int accelCallCount;
    accelCallCount++;
    if (accelCallCount % 100 == 0) {
        NSLog(@"accelCallCount:%d", accelCallCount);
    }

    //Use a basic low-pass filter to only keep the gravity in the accelerometer values
    accel[0] = acceleration.x * kFilteringFactor + accel[0] * (1.0 - kFilteringFactor);
    accel[1] = acceleration.y * kFilteringFactor + accel[1] * (1.0 - kFilteringFactor);
    accel[2] = acceleration.z * kFilteringFactor + accel[2] * (1.0 - kFilteringFactor);

    //Update the accelerometer values for the view
    [glView setAccel:accel];
}

该代码运行速度非常慢。从视觉上,我可以看出茶壶的运动变得非常延迟,而且变得越来越慢。最终,茶壶的移动很容易比我实际移动设备的时间延迟了 2 分钟以上。

调试器控制台中的输出也确实显示了一些延迟,但并不算太多。它几乎(但不完全)是应有速度的两倍。

2009-11-27 02:18:58.874 GLGravity[419:207] accelCallCount:100
2009-11-27 02:19:00.507 GLGravity[419:207] accelCallCount:200
2009-11-27 02:19:02.174 GLGravity[419:207] accelCallCount:300

不过,加速计回调似乎在某种队列中堆积起来。因此,一开始还不错的事情很快就会变得慢得难以忍受。

但是,如果我只是将 accelCallCount 的声明移动到头文件并将其声明为实例 var,这个问题就会消失:

int accelCallCount;

为什么会解决这个问题?

与此相关的是,无论我使用此代码还是“固定”(accelCallCount 作为 ivar)代码,如果我触摸屏幕,整个过程也会变慢。为什么会这样?

I'm playing with the GLGravity example to figure out some of the performance nuances related to dealing with the accelerometer.

Here's the problem code:

- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
    static int accelCallCount;
    accelCallCount++;
    if (accelCallCount % 100 == 0) {
        NSLog(@"accelCallCount:%d", accelCallCount);
    }

    //Use a basic low-pass filter to only keep the gravity in the accelerometer values
    accel[0] = acceleration.x * kFilteringFactor + accel[0] * (1.0 - kFilteringFactor);
    accel[1] = acceleration.y * kFilteringFactor + accel[1] * (1.0 - kFilteringFactor);
    accel[2] = acceleration.z * kFilteringFactor + accel[2] * (1.0 - kFilteringFactor);

    //Update the accelerometer values for the view
    [glView setAccel:accel];
}

This code runs very slowly. Visually, I can tell that the movement of the teapot becomes very delayed, and it just gets slower and slower. Eventually the teapot's movements are easily 2+ minutes delayed from the time I actually moved the device.

The output in the Debugger Console does show some delay, too, but it's not too much. It's nearly (but not quite) twice as slow as it should be.

2009-11-27 02:18:58.874 GLGravity[419:207] accelCallCount:100
2009-11-27 02:19:00.507 GLGravity[419:207] accelCallCount:200
2009-11-27 02:19:02.174 GLGravity[419:207] accelCallCount:300

Accelerometer callbacks seem to pile up, though, in some kind of queue. So what starts off as being not-too-bad quickly becomes unbearably slow.

This problem disappears, however, if I just move the declaration of accelCallCount to the header file and declare it as an instance var:

int accelCallCount;

Why does this fix it?

On a related note, whether I use this code or the "fixed" (accelCallCount as an ivar) code, the whole thing also slows down if I touch the screen. Why might that be?

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

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

发布评论

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

评论(2

红颜悴 2024-08-19 13:53:14

降低加速度计频率。

我将其降低到 50.0 Hz,加速更新事件停止累积,从而提高了渲染速度。在 50hz 下,应用程序运行完美(iPhone 无论如何都无法在 100hz 下渲染)。

#define kAccelerometerFrequency     50.0 // Hz

Reduce the accelerometer frequency.

I reduced it to 50.0 hz and the acceleration update events stopped building up, thus improving the rendering speed. At 50hz the app runs perfect (the iPhone cannot render at 100hz anyways).

#define kAccelerometerFrequency     50.0 // Hz
满栀 2024-08-19 13:53:14

您会收到很多事件,并且它们目前都在主线程上的委托方法本身中进行处理。如果发送给 glView 的消息也很昂贵,系统将处理该消息,并且传入事件将排队。

一个选项可能是批量处理委托调用中的事件,然后定期处理它们并获取摘要结果,然后更新显示。这也应该给主线程时间来处理触摸事件。

例如,将事件添加到委托方法中的数组中,其中的代码尽可能少(使数组预分配块使用头索引和尾索引进行循环),然后每 n 个事件分配一个线程处理它们,并使用 glView 更新值将其发送回主线程(或者更好的是,保持后台线程处于活动状态,定期进行处理,如果需要,使用信号量保护数据)。

另外,您可以在加速度计对象上设置 updateInterval,也许您只需要减慢速度?

至于实例与方法静态......我的猜测是实例变量将始终可以访问而无需开销,但方法内的静态访问成本相对较高。但这是值得注意的,也是我必须注意的事情。

希望这有帮助。

You get lots of events coming through, and they are all being processed in the delegate method itself at present, on the main thread. If your message to glView is expensive as well, the system will be processing that and incoming events will be queuing up.

An option might be to batch up the events in the delegate call, then periodically process them and take the summary result and then update the display. That should give the main thread time to handle touch events as well.

So for example, add the events to an array in the delegate method, with as little code as possible in there (make the array pre-allocated block that you loop over using head and tail indexes), then every n events, deach a thread to process them and have that post back to the main thread with the glView update values (or even better, keep a background thread alive that does the processing periodically, protecting the data with a semaphore if needed).

Also, you can set the updateInterval on the accelerometer object, maybe you just need to slow it down?

As for the instance vs method static... my guess is that the instance var will be accessible all the time without overhead, but the static within the method will be comparatively expensive to access. But that is noteworthy and something I will have to watch out for as well.

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文