Pregunta

Yo sé que si usted tiene un bucle que se modifica el recuento de los elementos en el circuito, utilizando el NSEnumerator en un conjunto es la mejor manera de asegurarse de que su código de golpes, sin embargo, me gustaría conocer el rendimiento de los equilibrios entre la NSEnumerator clase y sólo una vieja escuela de bucle

¿Fue útil?

Solución

El uso de las nuevas for (... in ...) la sintaxis de Objective-C 2.0 es generalmente la manera más rápida para iterar sobre una colección, porque se puede mantener un buffer en la pila y obtener lotes de elementos en él.

El uso de NSEnumerator generalmente es la más lenta de todas, porque a menudo copias de la colección se itera;para las colecciones inmutables esto puede ser barato (equivalente a -retain) pero para colecciones mutables puede causar una inmutable copia para ser creado.

Haciendo su propia repetición — por ejemplo, el uso de -[NSArray objectAtIndex:] — generalmente caen en algún lugar entre porque aunque no tenga el potencial de carga en la copia, usted también no será la obtención de lotes de objetos de la subyacente de la colección.

(PS - Esta pregunta debe ser etiquetada como Objective-C, no C, ya que NSEnumerator es un Cacao de la clase y el nuevo for (... in ...) la sintaxis es específico para Objective-C.)

Otros consejos

Después de la ejecución de la prueba varias veces, el resultado es casi el mismo.Cada medida de bloque se ejecuta 10 veces de forma consecutiva.

El resultado en mi caso desde la más rápida a la más lenta:

  1. Para..en (testPerformanceExample3) (0.006 seg)
  2. Mientras (testPerformanceExample4) (0.026 seg)
  3. For(;;) (testPerformanceExample1) (0.027 seg.)
  4. La enumeración de bloque (testPerformanceExample2) (0.067 s)

El for y while loop es casi el mismo.

comparation between iterations

El tmp es un NSArray que contiene 1 millón de objetos de 0 a 999999.

- (NSArray *)createArray
{
    self.tmpArray = [NSMutableArray array];
    for (int i = 0; i < 1000000; i++)
    {
        [self.tmpArray addObject:@(i)];
    }
    return self.tmpArray;
}

El código completo:

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

Para más información visite: Las manzanas "Acerca de las Pruebas con Xcode"

Son muy similares.Con Objective-C 2.0 la mayoría de las enumeraciones ahora defecto NSFastEnumeration que crea un búfer de las direcciones a cada objeto de la colección que se puede entregar.El paso que puede ahorrar con el clásico bucle for es no tener que llamar objectAtIndex:i cada vez que en el interior del bucle.Los componentes internos de la colección, al enumerar implementar rápida enumeración con llamadas objectAtIndex:i method.

El buffer es parte de la razón por la que usted no puede mutar una colección como la de enumerar, la dirección de los objetos que va a cambiar y el buffer que fue construido ya no coinciden.

Como un bono, el formato en el 2.0 se ve tan bonito como el clásico bucle for:

for ( Type newVariable in expression ) { 
    stmts 
}

Lea la siguiente documentación para profundizar más:NSFastEnumeration Protocolo De Referencia

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top