I was using
NSDateFormatter to parse date strings from a rails server and had thought nothing of it initially, but after running some tests it became clear I was wasting a lot of CPU cycles on this. Sam Soffes has written about similar results previously. For a quick test, fire up Code Runner and execute the block of code at the end of this README.
The gist of this code is that it generates an entire week worth of dates (one for every second) using
strftime_l(3) first and then
NSDateFormatter. It then parses them all using
strptime_l(3) first and
NSDateFormatter second, logging timings along the way. The results on my Mac this morning:
Creating 604800 date strings. Created date strings using strftime_l(3) -- 1.42116 seconds Created date strings using NSDateFormatter -- 1.74655 seconds Parsing 604800 date strings. Parsed date strings using strptime_l(3) -- 6.29914 seconds Parsed date strings using NSDateFormatter -- 26.842 seconds
It's clear that
NSString isn't hugely improved by using
strptime_l(3) is roughly 75% faster than
The project I was working on is already quite large, so I didn't want to end up diving into all the places I'm processing date strings and replace the simple
dateFromString: call with all the mess that is involved with using
NSString *dateString = ...; struct tm time; strptime_l([dateString cStringUsingEncoding:NSASCIIStringEncoding], formatString, &time, NULL); time_t timeInterval = mktime(&time); NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
And that's where STRFTimeFormatter comes in. I wrote this to be a drop in replacement for
NSDateFormatter1 that implements
dateFromString:, so I could just replace the
NSDateFormatter instances with instances of
STRFTimeFormatter and I get the performance boost without the headaches.
As always: forks, comments, issues, pull-requests - all welcome.
STRFTimeFormatterdoesn't actually inherit from
NSFormatter, so it isn't always API compatible. ↩