У меня есть словарь, содержащий второй словарь с 1000 записями.Все записи являются NSStrings типа ключ = key XXX
, а значение = element XXX
, где XXX
- это число между 0 - количество элементов - 1. (Несколько дней назад я спрашивал о словарях Objective-C, содержащихсловарь. Пожалуйста, обратитесь к этому вопросу , если вам нужен код, который создает словарь.)
Общая общая длина всех строк в под-словаре составляет 28 670 символов.то есть:
strlen("key 0")+strlen("element 0")+
//and so on up through
strlen("key 999")+strlen("element 999") == 28670.
Рассмотрим это очень простое хеш-значение в качестве индикатора, если метод перечислил каждую пару ключ + значение один раз и только один раз.
У меня есть одна подпрограмма, которая прекрасно работает (используя блоки) для доступа к отдельному ключу словаря и значениям:
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...
Если я попробую то же самое, используя параллельные блоки (на многопроцессорной машине), я получу число, близкое, но не совсем ожидаемое 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...
Документы Apple для NSEnumerationConcurrent
состояния:
"the code of the Block must be safe against concurrent invocation."
Я думаю, что это, вероятно, проблема, но в чем проблема с моим кодом или блоком в KVC_access4
что не безопасно для одновременного вызова?
Редактирование и заключение
Благодаря превосходному решению Б.Дж. Гомера, я получил работу NSEnumerationConcurrent.Я тщательно рассчитал оба метода.Код, приведенный выше в KVC_access3
, быстрее и проще для небольших и средних словарей.Это намного быстрее на многих словарях.Однако, если у вас есть большой словарь mongo (миллионы или десятки миллионов пар ключ / значение), тогда этот код:
[subDict
enumerateKeysAndObjectsWithOptions:
NSEnumerationConcurrent
usingBlock:
^(id key, id object, BOOL *stop) {
NSUInteger workingLength = [object length];
workingLength += [key length];
OSAtomicAdd64Barrier(workingLength, &ll);
}];
в 4 раза быстрее.Точка пересечения для размера составляет около 1 словаря из 100 000 моих тестовых элементов.Больше словарей и эта точка пересечения, вероятно, выше из-за времени настройки.