Mam słownik zawierający drugi słownik z 1000 wpisami. Wpisy są wszystkie NSStrings klucza typu = key XXX
, a wartość = element XXX
, gdzie XXX
jest liczbą między 0 - liczba elementów - 1. (Kilka dni temu, zapytałem o słowniki Objective-C zawierające słownik. Please refer to that question if chcesz kod, który tworzy słownik.)Objective-c: Problemy z blokami i NSEnumerationConcurrent
Suma całkowita długość wszystkich ciągów w podstronie jest 28 670 znaków. tj:
strlen("key 0")+strlen("element 0")+
//and so on up through
strlen("key 999")+strlen("element 999") == 28670.
Rozważ tę bardzo prostą wartość mieszania jako wskaźnik, jeśli metoda wyliczyła każdą parę klucz + wartość tylko raz.
Mam jeden podprogram, który działa doskonale (za pomocą bloków), aby uzyskać dostęp do indywidualnego klucza słownika i wartości:
NSUInteger KVC_access3(NSMutableDictionary *dict){
__block NSUInteger ll=0;
NSMutableDictionary *subDict=[dict objectForKey:@"dict_key"];
[subDict
enumerateKeysAndObjectsUsingBlock:
^(id key, id object, BOOL *stop) {
ll+=[object length];
ll+=[key length];
}];
return ll;
}
// will correctly return the expected length...
Gdyby spróbować tego samego z wykorzystaniem bloków współbieżnych (na multi maszynie procesora), otrzymuję liczba blisko, ale nie do końca oczekiwany 28670:
NSUInteger KVC_access4(NSMutableDictionary *dict){
__block NSUInteger ll=0;
NSMutableDictionary *subDict=[dict objectForKey:@"dict_key"];
[subDict
enumerateKeysAndObjectsWithOptions:
NSEnumerationConcurrent
usingBlock:
^(id key, id object, BOOL *stop) {
ll+=[object length];
ll+=[key length];
}];
return ll;
}
// will return correct value sometimes; a shortfall value most of the time...
Docs Jabłko dla NSEnumerationConcurrent
stanie:
"the code of the Block must be safe against concurrent invocation."
Myślę, że to prawdopodobnie problem, ale jaki jest problem z moim kodem lub blokiem w KVC_access4
, który NIE jest bezpieczny dla współbieżnego wywoływania?
Edytuj & Wnioski
Dzięki BJ Homera excellent solution, mam NSEnumerationConcurrent pracy. Dokładnie zaplanowałem obie metody. Kod, który mam powyżej w KVC_access3
jest szybszy i łatwiejszy dla małych i średnich słowników. O wiele szybciej na wielu słownikach. Jednakże, jeśli masz Mongo duży słowniku (miliony lub dziesiątki milionów par klucz/wartość) wtedy ten kod:
[subDict
enumerateKeysAndObjectsWithOptions:
NSEnumerationConcurrent
usingBlock:
^(id key, id object, BOOL *stop) {
NSUInteger workingLength = [object length];
workingLength += [key length];
OSAtomicAdd64Barrier(workingLength, &ll);
}];
jest do 4x szybciej. Punktem przecięcia dla rozmiaru jest około 1 słownik 100 000 z moich elementów testowych. Więcej słowników i ten punkt zwrotny jest wyższy, prawdopodobnie z powodu czasu konfiguracji.