При каких обстоятельствах GCD может негативно повлиять на производительность старых устройств? - PullRequest
0 голосов
/ 01 апреля 2012

Я испытываю что-то странное с GCD.

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

Без GCD пользовательский интерфейс останавливается примерно на 0,5 секунды каждый раз, когда вызывается этот метод.

Итак, я пошел в GCD и сделал следующее:

// INIT
// stored in ivar (called only once!)
dispatch_queue_t q = dispatch_queue_create("com.testcompany.myqueue", NULL);


// WORK
dispatch_async(q, ^(void) {
    [self performHeavyCalculationAndUpdateUI]; // modifies self.calculationData
});

После этого измененияЭтот метод занимает около 2-5 секунд , пока изменение не появится в пользовательском интерфейсе.

Рабочий код в -performHeavyCalculationAndUpdateUI:, выполняющийся в последовательной очереди, вызывает некоторый код модификации пользовательского интерфейса в основной очереди (основной поток) способ Роберт Райан предложил здесь :

dispatch_async(dispatch_get_main_queue(), ^{
    // Read ivars and objects used during calculation in the serial queue (problem?)
    CalculationData *result = self.calculationData;

    // UI updates like [foo addSubview:bar];
});

В основной очереди я также читаю некоторые ивары и объекты, которые использовались во время вычисления в последовательной фоновой очереди.Может ли это быть проблемой?

Это все еще занимает около 2-5 секунд, пока что-то не появляется.Намного дольше, чем без GCD.

Я не использую GCD нигде, кроме как здесь.

Кто-нибудь еще сталкивался с подобными проблемами с GCD и знает решение?

После нескольких часов я разобрался: Причина .

Ответы [ 2 ]

1 голос
/ 02 апреля 2012

Проблемы, которые вы описываете, не происходят от GCD, по крайней мере, в коде, который вы опубликовали. Я сделал функцию быстрого теста для регистрации времени, необходимого для переключения очередей:

-(IBAction)beginWork:(id)sender{
    NSTimeInterval buttonPushTime = [NSDate timeIntervalSinceReferenceDate];
    // Defined as an ivar : dispatch_queue_t q;
    // created as "q = dispatch_queue_create("com.testcompany.myqueue", NULL);" in viewDidLoad
    dispatch_async(q, ^{
        NSTimeInterval backgroundBeginTime = [NSDate timeIntervalSinceReferenceDate];
        [NSThread sleepForTimeInterval:5.0];
        NSTimeInterval backgroundEndTime = [NSDate timeIntervalSinceReferenceDate];
        dispatch_async(dispatch_get_main_queue(), ^{
            NSTimeInterval backOnMainThreadTime = [NSDate timeIntervalSinceReferenceDate];

            NSLog(@"seconds to start on background thread = %f",backgroundBeginTime-buttonPushTime);
            NSLog(@"seconds to perform in background      = %f",backgroundEndTime-backgroundBeginTime);
            NSLog(@"seconds to get main thread again      = %f",backOnMainThreadTime-backgroundEndTime);
            NSLog(@"total seconds                         = %f",backOnMainThreadTime-buttonPushTime);
        });
    });
}

Затем я запустил этот код на своем iPod touch 2-го поколения (возможно, очень старое устройство. IOS 4.2.1). Результаты были следующими:

seconds to start on background thread = 0.001747
seconds to perform in background      = 5.000142
seconds to get main thread again      = 0.000190
total seconds                         = 5.002079

Переключение очереди в этом случае добавило менее 2 тысячных секунды ко времени. Я рекомендую вам добавить несколько похожих журналов, чтобы найти задержку.

0 голосов
/ 01 апреля 2012

Кстати, вы выполняете dispatch_queue_create каждый раз, когда вызываете performHeavyCalculationAndUpdateUI? Вы выполняете этот тяжелый расчет много раз? Если это так, вы можете убедиться, что вы создаете очередь только один раз и отправляете ее по мере необходимости. (Отделение создания / выпуска очереди от того, что вы отправляете, также поможет вам определить причину проблемы с производительностью ... Затраты на GDC или некоторую проблему в performHeavyCalculationAndUpdateUI. Наконец, вы также выполняете dispatch_release, когда закончите с очередь?

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

...