Poniższy kod, który odwzorowuje proste obiekty wartościowe na obiekt, działa w Javie ponad 15 razy szybciej niż w Objective-C przy użyciu XCode 7 beta3, "Najszybsze, agresywne optymalizacje [-Ofast]". Mogę uzyskać ponad 280M odsyłaczy/sekundę w Javie, ale tylko około 19M w przykładzie objc. (Opublikowalam odpowiedni kod Javy tutaj, poniewaz rozpoczal to jako porównanie Swift: Swift Dictionary slow even with optimizations: doing uncessary retain/release?).NSMutableDictionary znacznie wolniejszy niż Java Map ... dlaczego?
To jest uproszczona wersja mojego prawdziwego kodu, który jest zdecydowanie związany z czasem szukania hash i wykazuje również tę ogólną różnicę wydajności. W poniższym teście testuję wartość null tylko po to, aby kompilator nie optymalizował wyszukiwania, ale w prawdziwej aplikacji używałbym tej wartości w większości przypadków.
Kiedy patrzę na instrumenty, widzę dużo czasu spędzonego na zachowaniu/zwolnieniu, msgSend i niektórych blokujących połączeniach, których nie rozumiem.
Wszelkie sugestie na temat tego, co może być przyczyną 10-15 razy wolniej niż Java lub wszelkie obejścia byłyby mile widziane. Mogę faktycznie zaimplementować idealny skrót taki jak ten poniżej, więc gdybym mógł go znaleźć, mógłbym użyć szybkiego słownika int-object dla systemu 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]);
}
Użycie 'NSNumber' w miejsce' MyKey' podwaja wydajność, wskazując, że 'MyKey' odpowiada za około 1/2 wydajności. Uzgodniono, że 'NSNumber' może nie być najlepszym testem wydajności. Istnieje jednak problem z synchronizacją metod hash i równości, a także tworzenie kluczowych obiektów do testu, które są częścią taktowania. – zaph
Nie próbuję argumentować, że Objective-C NSMutableDictionary jest nawet bliski prędkości podanej dla implementacji Java. Ale jestem zaskoczony różnicą. – zaph
Masz rację, że używanie NSNumber jest szybsze i nie wiem dlaczego. FYI, użyłem klawisza "mutable", aby uniknąć przydzielania pamięci w pętli odczytu. –