Я знаю, что если у вас есть цикл, который изменяет количество элементов в цикле, использование NSEnumerator в наборе - лучший способ убедиться, что ваш код взорван, однако я бы как понять компромисс производительности между классом NSEnumerator и только старой школой для петлиПроизводительность NSEnumerator против цикла в Cocoa
ответ
Используя новый синтаксис for (... in ...)
в Objective-C 2.0, как правило, самый быстрый способ перебора коллекции, поскольку он может поддерживать буфер в стеке и получать в него партии предметов.
Использование NSEnumerator
, как правило, самый медленный путь, поскольку он часто копирует повторяющуюся сборку; для неизменяемых коллекций это может быть дешево (эквивалентно -retain
), но для изменчивых коллекций он может создать неизменяемую копию.
Выполнение собственной итерации - например, с использованием -[NSArray objectAtIndex:]
- обычно будет находиться где-то посередине, потому что, в то время как у вас не будет потенциального скопирования накладных расходов, вы также не будете получать партии объектов из базовой коллекции.
(PS - Этот вопрос должен быть помечен, как Objective-C, а не C, так как NSEnumerator
класс какао и новый синтаксис for (... in ...)
специфичен для Objective-C.)
Они очень похожи. С Objective-C 2.0 в большинстве перечислений теперь по умолчанию используется NSFastEnumeration
, который создает буфер адресов для каждого объекта в коллекции, который он может доставить. Единственный шаг, который вы сохраняете в классическом цикле, - это не необходимость называть objectAtIndex:i
каждый раз внутри цикла. Внутренности коллекции, которую вы перечисляете, реализуют быстрое перечисление без вызова objectAtIndex:i method
.
Буфер является частью причины, по которой вы не можете мутировать коллекцию при перечислении, адрес объектов изменится, и созданный буфер больше не будет соответствовать.
В качестве бонуса формат в 2.0 выглядит так хорошо, как классический для цикла:
for (Type newVariable in expression) {
stmts
}
Прочитайте следующую documentaion углубиться: NSFastEnumeration Protocol Reference
После выполнения теста несколько раз, результат почти такой же. Каждый блок измерения выполняется 10 раз подряд.
В результате в моем случае от самой быстрой до медленной:
- for..in (testPerformanceExample3) (0,006 сек)
- Хотя (testPerformanceExample4) (0,026 сек)
- Для (;;) (testPerformanceExample1) (0.027 сек)
- блок Перечисление (testPerformanceExample2) (0,067 сек)
для и в то время цикла почти то же самое.
tmp
является NSArray
, который содержит 1 миллион объектов от 0 до 999999.
- (NSArray *)createArray
{
self.tmpArray = [NSMutableArray array];
for (int i = 0; i < 1000000; i++)
{
[self.tmpArray addObject:@(i)];
}
return self.tmpArray;
}
Весь код:
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) NSMutableArray *tmpArray;
- (NSArray *)createArray;
@end
ViewController .m
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self createArray];
}
- (NSArray *)createArray
{
self.tmpArray = [NSMutableArray array];
for (int i = 0; i < 1000000; i++)
{
[self.tmpArray addObject:@(i)];
}
return self.tmpArray;
}
@end
MyTestfile.m
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "ViewController.h"
@interface TestCaseXcodeTests : XCTestCase
{
ViewController *vc;
NSArray *tmp;
}
@end
@implementation TestCaseXcodeTests
- (void)setUp {
[super setUp];
vc = [[ViewController alloc] init];
tmp = vc.createArray;
}
- (void)testPerformanceExample1
{
[self measureBlock:^{
for (int i = 0; i < [tmp count]; i++)
{
[tmp objectAtIndex:i];
}
}];
}
- (void)testPerformanceExample2
{
[self measureBlock:^{
[tmp enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {
obj;
}];
}];
}
- (void)testPerformanceExample3
{
[self measureBlock:^{
for (NSNumber *num in tmp)
{
num;
}
}];
}
- (void)testPerformanceExample4
{
[self measureBlock:^{
int i = 0;
while (i < [tmp count])
{
[tmp objectAtIndex:i];
i++;
}
}];
}
@end
Для получения дополнительной информации посетите: Apples "About Testing with Xcode"
- 1. цикла против цикла в обратном направлении: производительность
- 2. производительность между таймером против цикла в java swing?
- 3. Производительность традиционных для цикла против Iterator/foreach в Java
- 4. Какова ценность NSEnumerator?
- 5. Когда заканчивается NSEnumerator?
- 6. MonoTouch - foreach против циклов (производительность)
- 7. Производительность сокетов против труб
- 8. Производительность против качества кода
- 9. Производительность против читаемости
- 10. Производительность тяги против cublas
- 11. Производительность: Просмотр против подвыбор
- 12. Производительность против списков памяти
- 13. Производительность массива против карты
- 14. Производительность ArrayList против HashSet
- 15. Производительность ReceiveAsync против BeginReceive
- 16. Производительность против чистого кода?
- 17. Производительность auto_ptr против shared_ptr
- 18. SQL: производительность против читаемости
- 19. Производительность: SortedDictionary против SortedSet
- 20. Производительность против правильности/предпочтения?
- 21. ключи против значений производительность
- 22. Возможно NSIndexSet для преобразования NSEnumerator?
- 23. Как использовать NSEnumerator с NSMutableDictionary?
- 24. Делегаты против событий в Cocoa Touch
- 25. производительность Linq2SQL против пользовательских DAL против NHibernate
- 26. DataTable производительность цикла
- 27. C++ производительность вложенного цикла
- 28. Получить максимальную производительность цикла
- 29. Java производительность бесконечного цикла
- 30. Для цикла пропускается в Cocoa Touch
@Jeff Atwood, что ссылка не работает для меня. Вместо этого я просто установил Xcode 4. Я искал «NSFastEnumeration» в документации Xcode и API Reference, чтобы найти ссылку на NSFastEnumeration Protocol. – ma11hew28 2011-04-17 03:22:48
@matt в будущем нажмите «отредактировать» и сделайте сообщение лучше для наших попутчиков. Я не занимаюсь разработкой iOS .. :) – 2011-04-17 03:32:35