2009-09-09 9 views
2

Grâce aux répondants à cette question (This loop is very slow, I think because I create a lot of intermediate strings. How can I speed it up?), j'ai été en mesure d'accélérer mon code de plusieurs ordres de grandeur.Une autre augmentation de vitesse possible?

Je pense que je peux probablement faire un peu mieux cependant. Est-il possible d'éviter la création d'un groupe de NSString ici, et à la place diviser le grand NSString (routeGeom) en un tas de tampons char et itérer à travers ceux-ci?

Je n'ai jamais fait de programmation en C, donc si vous savez comment y arriver, ce serait très apprécié!

NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; 

NSString *routeGeom = [pieces objectAtIndex:1]; 
NSArray *splitPoints = [routeGeom componentsSeparatedByString:@"],["]; 

routePoints = malloc(sizeof(CLLocationCoordinate2D) * ([splitPoints count] + 1)); 

int i=0; 
for (NSString* coordStr in splitPoints) { 

    char *buf = [coordStr UTF8String]; 
    sscanf(buf, "%f,%f,", &routePoints[i].latitude, &routePoints[i].longitude); 

    i++; 

} 
+1

Avez-vous profilé et déterminé que le fractionnement de la chaîne prend beaucoup de temps? – Chuck

+0

Maintenant que [neutrinos pourrait aller encore plus vite que c] (http://science.slashdot.org/story/11/09/22/1841217/cern-experiment-indicates-faster-than-light-neutrinos), pourrait vouloir essayer une implémentation en utilisant ceux-ci. –

Répondre

1
char *buf = [routeGeom UTF8String]; 
int bestGuess = 1 << (whatever); 
routePoints = malloc(sizeof(CLLocationCoordinate2D) * bestGuess); 
for (int i = 0; buf != NULL; buf = strchr(buf+1,'['), ++i) { 
    if (i >= bestGuess) { 
     bestGuess <<= 1; 
     routePoints = realloc(routePoints, sizeof(CLLocationCoordinate2D) * bestGuess); 
    } 
    sscanf(buf+1, "%f,%f,", &(routePoints + i)->latitude, &(routePoints + i)->longitude); 
} 


choisir une bonne valeur de départ pour (whatever) de sorte que 2 quel que soit est représentatif d'un nombre moyen de points dans un itinéraire. Si vous ne pouvez pas, vous pouvez essayer de deviner le nombre en fonction de la longueur de la chaîne. Sinon, si vous voulez être précis, vous pouvez analyser la chaîne deux fois, compter d'abord, puis créer routePoints, puis analyser les données, auquel cas vous n'aurez pas besoin de la section realloc.

Edit:

Une autre option. Cela suppose que CLLocationCoordinate2D est simplement une structure de 2 flottants, dans le même ordre que les données de la chaîne.

char *buf = [routeGeom UTF8String]; 
int bestGuess = 1 << (whatever); 
float *tmpFloats = (float *)malloc(sizeof(float) * bestGuess); 
float *index = tmpFloats; 
for (int i = 0; buf != NULL; buf = strchr(buf+1,'['), ++i, index += 2) { 
    if (i >= bestGuess) { 
    bestGuess <<= 1; 
    tmpFloats = (float *)realloc(tmpFloats, sizeof(float) * bestGuess); 
    } 
    sscanf(buf+1, "%f,%f,", index, index + 1); 
} 
CLLocationCoordinate2D *routePoints = (CLLocationCoordinate2D *)tmpFloats; 
+0

Je ne sais pas pourquoi, mais cette boucle ne s'arrête jamais pour moi. –

+0

J'ai obtenu ce code, mais c'est beaucoup plus lent que le code original. –

+0

Si vous avez choisi un mauvais choix pour bestGuess, le code peut devenir très lent, s'il doit réallouer la mémoire; Si vous ne pouvez pas trouver de bonnes valeurs de base (surestimer plutôt que sous-estimer si une estimation est nécessaire), il peut être judicieux de compter d'abord le nombre d'ensembles, ensuite malloc, puis d'analyser les données. Une autre idée serait d'utiliser memchr au lieu de strchr. –

0

Vous devriez vraiment utiliser NSScanner pour cette tâche - bitbanging des augmentations de performance miniscule est vraiment ne vaut pas le temps.

+0

Avez-vous recherché "scanner"? –

1

Retirez le realloc, il existe une meilleure façon de le faire. Aussi, vous ne devriez pas itérer sur une boucle en utilisant arrayname [index]. Au lieu d'utiliser un pointeur, ce

int array[5000]; 
int* intPointer = &array; 
for(int i=0;i<5000;i++,intPointer++) 
    *intPointer = something 

Faire &routePoints[i] force le CPU pour faire un '& points de route + i * sizeof (CLLocationCoordinate2D) » plusieurs fois par boucle.

je vous recommandons fortement de vous procurer un livre sur C et apprenez-le, vous en bénéficierez à long terme

Je sais que cette réponse ne vous aide pas immédiatement, mais prendre une très longue chaîne et la diviser en plus petites chaînes en utilisant C est en fait une chose très commune et simple faire (d'une manière très rapide et efficace)

Questions connexes