I am calling strtoull() over 100 million times in my command line Objective-C OS X app calculating Hamming distance. I have tracked down a ~30 byte/call memory leak to this function call from ph_hamming_distance(). I have looked at the BSD source for strtoull() and even chopped out the generality I don't need and put the source inside my app but still have the memory leak.
The calling code is:
NSArray * returnMatchedImagesFromDB(NSString * hash, NSString * asin, NSInteger action) {
/* Input hash, asin, action(not yet used)
* Calculate Hamming Distance to all records in DB
* Return NSArray of HammingDistanceRecords of matches within "hdCompareThreshold" of each other
*/
int hd;
int threshold = 0;
NSMutableArray * retArray = [[NSMutableArray alloc] init];
threshold = hdCompareThreshold;
// for each image in dbImageArray, compute hamming distance to all other images
for (ImageRecord *imgRecord in dbImageArray) {
hd = ph_hamming_distance(imgRecord.hash, hash);
if ((threshold == -1) || (hd <= threshold)) {
HammingDistanceRecord * hdRec = [[HammingDistanceRecord alloc] init];
hdRec.hammingDistance = hd;
hdRec.asin1 = asin;
hdRec.asin2 = imgRecord.asin;
hdRec.rank2 = imgRecord.rank;
[retArray addObject:hdRec];
}
}
return [retArray copy];
} // returnMatchedImagesFromDB()
int ph_hamming_distance(NSString * hashStr1,NSString * hashStr2) {
NSUInteger hash1 = strtoull([hashStr1 UTF8String],NULL,0);
NSUInteger hash2 = strtoull([hashStr2 UTF8String],NULL,0);
NSUInteger x = hash1^hash2;
const NSUInteger m1 = 0x5555555555555555ULL;
const NSUInteger m2 = 0x3333333333333333ULL;
const NSUInteger h01 = 0x0101010101010101ULL;
const NSUInteger m4 = 0x0f0f0f0f0f0f0f0fULL;
x -= (x >> 1) & m1;
x = (x & m2) + ((x >> 2) & m2);
x = (x + (x >> 4)) & m4;
return (x * h01)>>56;
}
The arguments to ph_hamming_distance() are always base10 (with no alpha chars). Typical hashStr is @"17609976980814024116". The database of objects I am comparing is currently at 390K objects so an internal compare of all the objects against themselves is 300 billion calls to strtoull(). The leak is causing my app to SIGKILL -9 at ~3500 compares every time. This is 3500*390K*2 calls/compare = ~80 GB which is my free space on my drive, so I guess OS X is killing the process when the swapfile fills up the drive.
Any help appreciated.