Od czasu do czasu zauważam, że używam bloku do iteracji nad kolekcją bez zapisywania do współdzielonych danych lub wywoływania jakichkolwiek skutków ubocznych. Zastanawiam się nad dodaniem opcji NSEnumerationConcurrent, a następnie odrzuć ją, ponieważ nie rozumiem, kiedy warto jej użyć.Kiedy używać NSEnumerationConcurrent
Mam więc konkretne pytanie i bardziej ogólne.
Pierwsze pytanie: Oto może nieznacznie wymyślony przykład użycia bloku zrobić coś trywialnego dwutorowo:
CGFloat GetAverageHeight(NSArray* people)
{
NSUInteger count = [people count];
CGFloat* heights = malloc(sizeof(CGFloat) * count);
[people enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock:
^(id person, NSUInteger idx, BOOL* stop)
{
heights[idx] = [person height];
}];
CGFloat total= 0.0;
for (size_t i = 0 ; i < count ; i++) total += heights[i];
free(heights);
return total/count;
}
ignorując fakt, że zakaz równoczesnego wyliczenie mogło tylko podsumować wysokość bezpośrednio, bez konieczności za wywołanie funkcji malloc lub drugiej połowy funkcji, czy jest jakiś punkt używający tutaj NSEnumerationConcurrent? Czy obciążenie związane z używaniem GCD (lub cokolwiek NSEnumerationConcurrent nie działa w tle) neguje zysk jednoczesnego uzyskiwania banalnej własności? O ile mniej trywialna musi być praca bloku, zanim warto skorzystać z NSEnumerationConcurrent?
Drugie pytanie: Bardziej ogólnie, czy powinienem uważać współbieżność za coś, co powinienem wykorzystać, gdy widzę taką możliwość (rationale: przypuszczalnie punktem tych API jest to, że współdziałają mniej ze specjalnym przypadkiem i większą częścią ogólnego wyglądu programu), lub tylko optymalizacji, której powinienem użyć tylko wtedy, gdy znalazłem konkretny problem z wydajnością i wierzę, że współbieżność jest odpowiedzią (racjonalne: błędy w kodzie współbieżnym są koszmarem do wyśledzenia)?