Почему использование статического int в моем обратном вызове акселерометра намного медленнее, чем использование переменной экземпляра? - PullRequest
0 голосов
/ 27 ноября 2009

Я играю с примером 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) код, все это также замедляется, если я касаюсь экрана. Почему это может быть?

Ответы [ 2 ]

1 голос
/ 05 января 2010

Уменьшите частоту акселерометра.

Я уменьшил его до 50,0 Гц, и события обновления ускорения перестали накапливаться, что улучшило скорость рендеринга. На частоте 50 Гц приложение работает идеально (iPhone все равно не может воспроизводить на частоте 100 Гц).

#define kAccelerometerFrequency     50.0 // Hz
0 голосов
/ 27 ноября 2009

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

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

Так, например, добавьте события в массив в методе делегата, используя как можно меньше кода (сделайте предварительно выделенный блок массива, который вы зацикливаете, используя индексы head и tail), затем каждые n событий, проследить за тем, чтобы обработать их, и отправить эту запись обратно в основной поток со значениями обновления glView (или, что еще лучше, поддерживать фоновый поток в актуальном состоянии, который периодически выполняет обработку, при необходимости защищая данные семафором).

Кроме того, вы можете установить updateInterval для объекта акселерометра, может быть, вам просто нужно замедлить его?

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

Надеюсь, это поможет.

...