Alejandro Luengo
Alejandro Luengo

Reputation: 1364

Speeding up a loop to create a long string

I am creating a very long string by formatting NSNumbers in four different arrays:

NSString *datos = @"";

for (NSInteger counter = 0; counter < [latOut count]; counter++) {
    datos = [datos stringByAppendingString:[NSString stringWithFormat:@"%.0005f,", [[latOut objectAtIndex:counter] floatValue]]];
    datos = [datos stringByAppendingString:[NSString stringWithFormat:@"%.0005f,", [[lonOut objectAtIndex:counter] floatValue]]];
    datos = [datos stringByAppendingString:[NSString stringWithFormat:@"%ld,", [[tipoOut objectAtIndex:counter] integerValue]]];
    datos = [datos stringByAppendingString:[NSString stringWithFormat:@"%ld\n", [[velocidadOut objectAtIndex:counter] integerValue]]];
}

NSString *curDir = [[NSFileManager defaultManager] currentDirectoryPath];

NSString *path = @"";
path = [path stringByAppendingPathComponent:curDir];
path = [path stringByAppendingPathComponent:@"data.csv"];

// Y luego lo grabamos
[datos writeToFile:path atomically:YES encoding:NSASCIIStringEncoding error:&error];

The count is 18,000 entries, and this loop takes almost 2 minutes to complete.

How could I make this much faster?

Upvotes: 1

Views: 94

Answers (2)

jscs
jscs

Reputation: 64002

Your memory consumption is also likely mindblowing. Use a mutable string instead of creating thousands of temporary strings:

NSMutableString *datos = [NSMutableString string];

for (NSInteger counter = 0; counter < [latOut count]; counter++) {
    [datos appendFormat:@"%.0005f, %.0005f, %ld, %ld\n", [[latOut objectAtIndex:counter] floatValue], 
                                                         [[lonOut objectAtIndex:counter] floatValue], 
                                                         [[tipoOut objectAtIndex:counter] integerValue], 
                                                         [[velocidadOut objectAtIndex:counter] integerValue]];
}

Upvotes: 2

Jack
Jack

Reputation: 133567

The main suggestion I see here, since you are working a lot with strings, is to use NSMutableString which should be much more efficient:

// give a good estimate of final capacity
NSMutableString *datos = [[NSMutableString alloc] initWithCapacity:100000];

for (NSInteger counter = 0; counter < [latOut count]; counter++) {
  [datos appendFormat:@"%.0005f", [[latOut objectAtIndex:counter] floatValue]];
  ...
}

This will avoid a lot of unnecessary temporary immutable string allocations.

Upvotes: 4

Related Questions