Следующий код, который сопоставляет простые носители значений объекту, работает быстрее на Java быстрее, чем Objective-C, используя XCode 7 beta3, "Быстрая, агрессивная оптимизация [-Ofast]". Я могу получить более 280 М поисков/сек в Java, но только около 19 М в примере objc. (Я отправил соответствующий Java-код здесь, поскольку это началось как сравнение Swift: Swift Dictionary медленный даже с оптимизацией: выполнение незавершенного сохранения/выпуска?).
Это упрощенная версия моего реального кода, который определенно связан с временем поиска хэша и демонстрирует эту общую разницу в производительности. В тесте ниже я тестирую значение null, чтобы убедиться, что компилятор не оптимизирует поиск, но в реальном приложении я бы использовал значение в большинстве случаев.
Когда я смотрю на инструменты, я вижу много времени, потраченного на сохранение/освобождение, msgSend и некоторые блокирующие вызовы, которые я не понимаю.
Любые идеи о том, что может объяснить это, на 10-15 раз медленнее, чем Java, или любые обходные пути, будут оценены. Я могу на самом деле реализовать идеальный хэш, как тот, который приведен ниже, поэтому я мог бы использовать быстрый словарь int-object для iOS, если бы мог найти его.
@interface MyKey : NSObject <NSCopying>
@property int xi;
@end
@implementation MyKey
- (NSUInteger)hash { return self.xi; }
- (BOOL)isEqual:(id)object { return ((MyKey *)object).xi == self.xi; }
- (id)copyWithZone:(NSZone *)zone { return self; }
@end
NSMutableDictionary *map = [NSMutableDictionary dictionaryWithCapacity:2501];
NSObject *obj = [[NSObject alloc] init];
int range = 2500;
for (int x=0; x<range; x++) {
MyKey *key = [[MyKey alloc] init];
key.xi=x;
[map setObject:obj forKey:key];
}
MyKey *key = [[MyKey alloc] init];
int runs = 50;
for (int run=0; run<runs; run++)
{
NSDate *start = [NSDate date];
int reps = 10000;
for(int rep=0; rep<reps; rep++)
{
for (int x=0; x<range; x++) {
key.xi=x;
if ( [map objectForKey:key] == nil ) { NSLog(@"missing key"); }
}
}
NSLog(@"rate = %f", reps*range/[[NSDate date] timeIntervalSinceDate:start]);
}