Первое, что нужно попробовать, - это преобразовать DISPATCH_QUEUE_PRIORITY_HIGH (он же ONG MOST ВАЖНАЯ РАБОТА, КОГДА-ЛИБО ЗАБЫТЬ ВСЕ ЕЩЕ) в что-то вроде DISPATCH_QUEUE_PRIORITY_LOW.
Если это не исправить, вы можете попытаться выполнить трафик http через диспетчеризациюно это большая работа.
Вы также можете просто попытаться ограничить число http-выборок в полете с семафором, реальный трюк будет в том, чтобы решить, каков наилучший предел, поскольку "хорошее" число будетзависит от сети, ваших процессоров и нагрузки на память.Может быть, тесты 2, 4 и 8 с несколькими конфигурациями и посмотреть, достаточно ли шаблон для обобщения.
Хорошо, давайте попробуем только один, замените queue = ...
на:
static dispatch_once_t once;
static dispatch_queue_t queue = NULL;
dispatch_once(&once, ^{
queue = dispatch_queue_create("com.blah.url-fetch", NULL);
});
Оставьте остальную часть кода как есть.Скорее всего, это будет наименьшее количество брызг, но может не загружать изображения очень быстро.
В более общем случае вырвите изменение, которое я только что дал вам, и мы поработаем над этим:
dispatch_async(queue, ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
dispatch_async(dispatch_get_main_queue(), ^{
[self writeImageData:UIImagePNGRepresentation(image) toFilePath:filePathForURL(url)];
_block(image);
});
});
Замена на:
static dispatch_once_t once;
static const int max_in_flight = 2; // Also try 4, 8, and maybe some other numbers
static dispatch_semaphore_t limit = NULL;
dispatch_once(&once, ^{
limit = dispatch_semaphore_create(max_in_flight);
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(limit, DISPATCH_TIME_FOREVER);
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
// (or you might want the dispatch_semaphore_signal here, and not below)
dispatch_async(dispatch_get_main_queue(), ^{
[self writeImageData:UIImagePNGRepresentation(image) toFilePath:filePathForURL(url)];
_block(image);
dispatch_semaphore_signal(limit);
});
});
ПРИМЕЧАНИЕ : я не тестировал ни один из этого кода, даже чтобы посмотреть, компилируется ли он.Как написано, это позволит только двум потокам выполнять большую часть кода в ваших двух вложенных блоках.Возможно, вы захотите переместить dispatch_semaphore_signal вверх в закомментированную строку.Это ограничит вас двумя выборками / созданием изображения, но им будет разрешено перекрываться с записью данных изображения в файл и вызовом вашего обратного вызова _block.
Кстати, вы делаете много файлового ввода-вывода, которыйбыстрее на флэш-памяти, чем на любом другом диске, но если вы все еще ищете выигрыши в производительности, это может стать еще одним местом для атаки.Например, возможно, хранить UIImage в памяти до тех пор, пока вы не получите предупреждение о нехватке памяти и только потом записать их на диск.