NSEnumerator performance vs für Schleife in Kakao
-
09-06-2019 - |
Frage
Ich weiß, dass, wenn Sie haben eine Schleife, die ändert die Anzahl der Elemente in der Schleife, mit der NSEnumerator auf ein einstellen, ist der beste Weg, um sicherzustellen, dass Ihr code in die Luft sprengt, jedoch würde ich gerne verstehen, die performance-Unterschiede zwischen den NSEnumerator Klasse und nur eine old-school-Schleife
Lösung
Mit dem neuen for (... in ...)
syntax in Objective-C 2.0 ist in der Regel der Schnellste Weg zum Durchlaufen einer Sammlung, weil es pflegen einen Puffer auf dem stack und erhalten Stapel von Elementen in es.
Verwendung NSEnumerator
ist in der Regel der langsamste Weg, weil es oft kopiert die collection iterieren;für unveränderliche Sammlungen diese kann Billig sein, (entspricht -retain
), aber für die veränderlichen collections, die es verursachen kann, eine unveränderliche Kopie erstellt werden.
Tun, Ihre eigene iteration — zum Beispiel mit -[NSArray objectAtIndex:]
— wird im Allgemeinen fallen irgendwo dazwischen, denn während Sie nicht das Potenzial haben, kopieren overhead, wirst du auch nicht bekommen Chargen von Objekten aus der zugrunde liegenden Auflistung.
(PS - Diese Frage sollte tagged as Objective-C, nicht C, da NSEnumerator
ist eine Cocoa-Klasse und der neue for (... in ...)
syntax ist spezifisch für Objective-C.)
Andere Tipps
Nach Durchführung des Tests mehrmals, das Ergebnis ist fast das gleiche.Jede Maßnahme block läuft 10-mal hintereinander.
Das Ergebnis ist in meinem Fall von der schnellsten zur langsamsten:
- For..in - (testPerformanceExample3) (0.006 Sekunden)
- Während (testPerformanceExample4) (0.026 Sek)
- For(;;) (testPerformanceExample1) (0.027 Sekunden)
- Enumeration block (testPerformanceExample2) (0.067 Sek.)
Die for-und die while-Schleife ist fast das gleiche.
Die tmp
ist ein NSArray
enthält 1 million Objekte von 0 bis 999999.
- (NSArray *)createArray
{
self.tmpArray = [NSMutableArray array];
for (int i = 0; i < 1000000; i++)
{
[self.tmpArray addObject:@(i)];
}
return self.tmpArray;
}
Der gesamte code:
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
Für weitere Informationen besuchen Sie: Äpfel "zum Testen mit Xcode"
Sie sind sich sehr ähnlich.Mit Objective-C 2.0 meisten Aufzählungen, die jetzt standardmäßig NSFastEnumeration
das schafft einen Puffer, mit dem die Adressen auf jedes Objekt in der Sammlung, dann kann es liefern.Der eine Schritt, den Sie speichern über die klassische for-Schleife ist nicht mit zu nennen objectAtIndex:i
jedes mal in der Schleife.Die Interna der Kollektion, die Sie aufzählen Umsetzung schnell Aufzählung heraus aufrufen objectAtIndex:i method
.
Der Puffer ist ein Teil des Grundes, dass Sie können nicht mutieren einer Sammlung, wie Sie auflisten, die Adresse der Objekte ändern wird und der Puffer, der gebaut wurde, wird nicht mehr übereinstimmen.
Als bonus-format in 2.0 sieht so schön, wie die klassische for-Schleife:
for ( Type newVariable in expression ) {
stmts
}
Lesen Sie die folgenden documentaion, um tiefer zu gehen:NSFastEnumeration-Protokoll-Referenz