Obj-C performance week 2: Numbers to strings

Thoughts By 4 years ago

In this weeks performance comparison I will be comparing convering a number to a string.

There are two common ways of doing this.

NSNumber’s stringValue

This method involves first turning your primitive number type into a obj-c wrapped type of NSNumber, then calling it’s stringValue method to get a string representation of the number.

NSString’s initWithFormat:

Using initWithFormat:, the type of the number must be known, and then can be converted using a format such as @”%d” (integers) or @”%f” (floats) etc etc.

The results

initWithFormat: is clearly better in terms of performance…


At first this was surprising for me. How could it be that a method on NSNumber yields slower results compared to using the number with a format string? I turned to the time profiler to find out. I found that NSNumber‘s stringValue method still uses initWithFormat: under the hood, meaning there’s slight overhead from determining the datatype, then figuring out which format to use. Of course if you manually specify a format string then this doesn’t need to happen, and things may be quicker.

However, the trade off of manually using a format string with initWithFormat: is that you must know the primitive value’s type. This can be a pain especially when Mac and iOS went from 32 bit to 64 bit, when an NSUInteger went from an unsigned int to an unsigned long depending on which architecture you were compiling for. Considering this, I still personally prefer using the NSNumber method.

If you are a speed freak, then look past both of these and instead try sprintf() or one of it’s similar functions.

The code

If you want to run the same tests, my code is as follows. Done 3 million times to separate each test by mere milliseconds.

#define TEST_FORMAT 2


const CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();

for(NSUInteger i = 0; i < 3000000; i++)
	NSString* result = @(42).stringValue;
	NSString* result = [NSString stringWithFormat:@"%d", 42];

const CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();

NSLog(@"%f seconds", end - start);