Ответ 1
Если скорость выполнения (не скорость программирования) важна, то явный цикл является самым быстрым. Я провел следующие тесты с массивом из 1000000 случайных чисел:
Версия 1: сортировка массива:
NSArray *sorted1 = [numbers sortedArrayUsingSelector:@selector(compare:)];
// 1.585 seconds
Версия 2: кодирование с ключом, используя "doubleValue":
NSNumber *max=[numbers valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numbers valueForKeyPath:@"@min.doubleValue"];
// 0.778 seconds
Версия 3: кодирование с ключом, используя "self":
NSNumber *max=[numbers valueForKeyPath:@"@max.self"];
NSNumber *min=[numbers valueForKeyPath:@"@min.self"];
// 0.390 seconds
Версия 4: Явный цикл:
float xmax = -MAXFLOAT;
float xmin = MAXFLOAT;
for (NSNumber *num in numbers) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
// 0.019 seconds
Версия 5: Перечисление блоков:
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
[numbers enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}];
// 0.024 seconds
Программа тестирования создает массив из 1000000 случайных чисел, а затем применяет все сортировки методы для одного и того же массива. Вышеуказанные тайминги являются результатом одного запуска, но я делаю около 20 прогонов с очень похожими результатами в каждом прогоне. Я также изменил порядок, в котором применяются 5 методов сортировки для исключения эффектов кеширования.
Обновление: Я создал (надеюсь) лучшую тестовую программу. Полный исходный код находится здесь: https://gist.github.com/anonymous/5356982. Среднее время для сортировки массив из 1000000 случайных чисел (в секундах, на 3,1 ГГц Core i5 iMac, выпуск компиляции):
Sorting 1.404 KVO1 1.087 KVO2 0.367 Fast enum 0.017 Block enum 0.021
Обновление 2: Как видно, быстрое перечисление выполняется быстрее, чем перечисление блоков (что также указано здесь: http://blog.bignerdranch.com/2337-incremental-arrayification/).
РЕДАКТИРОВАТЬ: Неправильно следующее: я забыл инициализировать объект, используемый как блокировка, как правильно заметил Hot Licks, так что синхронизация вообще не выполняется.
И с lock = [[NSObject alloc] init];
параллельное перечисление настолько медленное
что я не осмеливаюсь показать результат. Возможно, более быстрый механизм синхронизации может
помощь...)
Это резко меняется, если вы добавите параметр NSEnumerationConcurrent
к
перечисление блока:
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
id lock;
[numbers enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
@synchronized(lock) {
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
}];
Сроки здесь
Concurrent enum 0.009
так что это примерно в два раза быстрее, чем быстрое перечисление. Результат, вероятно, не является репрезентативным потому что это зависит от количества доступных потоков. Но интересно все равно! Обратите внимание, что я использовали "самый простой в использовании" метод синхронизации, который может быть не самым быстрым. Забастовкa >