[GCD] NSOpérations: des conflits d'accès à des "données en lecture seule" ?
ClicCool
Membre
Grâce à Ali il me semble avoir une bonne répartition de mes nombreuses tâches.
Pour autant j'assiste à des plantages épisodiques et surtout fort rares rendant le débug de mes centaines de taches un peu difficile. ???
Peut-être cela vient-il du fait que toutes ces taches partagent les mêmes ressources de travail à savoir un NSArray (non mutable) de NSString (non mutables).
La doc Apple me dit en effet:
Il faudrait donc que chaque opération reçoive une copie du NSArray de travail.
MAIS celui-ci est fort lourd et les tâches peuvent être fort nombreuses (plusieurs centaines).
Ce qui ferait potentiellement une sacrée consommation mémoire.
De plus, mes opérations ne font QUE de la lecture sur le NSArray et ses NSStrings. Et ces string, une fois mises en place dans le NSArray, AVANT le lancement des opérations, ne seront jamais modifiées nulle part dans le code.
(elle seront même releasées dès que toutes les NSOpérations auront effectué travail).
Ma question est donc, pour des tâches se contentant de lire leur données de travail, faut-il néanmoins mettre en place une protection ou leur transmettre une copie de travail ?
Et, si oui, vaut-il mieux
C'est que je voudrais pas ralentir trop l'exécution
Mais je souhaites pas non plus me faire épingler par la sécu pour Arrays de Travail abusifs :P
Pour autant j'assiste à des plantages épisodiques et surtout fort rares rendant le débug de mes centaines de taches un peu difficile. ???
Peut-être cela vient-il du fait que toutes ces taches partagent les mêmes ressources de travail à savoir un NSArray (non mutable) de NSString (non mutables).
La doc Apple me dit en effet:
The simplest and easiest way to avoid thread-related resource conflicts is to give each thread in your program its own copy of whatever data it needs
Il faudrait donc que chaque opération reçoive une copie du NSArray de travail.
MAIS celui-ci est fort lourd et les tâches peuvent être fort nombreuses (plusieurs centaines).
Ce qui ferait potentiellement une sacrée consommation mémoire.
De plus, mes opérations ne font QUE de la lecture sur le NSArray et ses NSStrings. Et ces string, une fois mises en place dans le NSArray, AVANT le lancement des opérations, ne seront jamais modifiées nulle part dans le code.
(elle seront même releasées dès que toutes les NSOpérations auront effectué travail).
Ma question est donc, pour des tâches se contentant de lire leur données de travail, faut-il néanmoins mettre en place une protection ou leur transmettre une copie de travail ?
Et, si oui, vaut-il mieux
- Privilégier une occupation mémoire réduite et mettre en place des Mutex ?
- Privilégier la rapidité d'exécution et transmettre une copie de travail du NSArray à chaque NSOpération ?
C'est que je voudrais pas ralentir trop l'exécution
Mais je souhaites pas non plus me faire épingler par la sécu pour Arrays de Travail abusifs :P
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Moi je ferais un wrapper pour cet NSArray avec cette méthode:
Si ça plante encore c'est que le problème est ailleurs
J'avais pas du tout pensé à mixer des @synchronized et des copies à la volée.
C'est peut-être le juste milieu que je cherchais ça !
Merci Mpergand
C'est très étrange. Vu ce que tu dis, tout est censé être thread safe. Tu as un log du plantage et de la pile d'appel au moment de la violation d'accès?
Parce que clairement, l'avantage des objets non mutables, c'est qu'ils ne posent justement pas de problèmes d'accès concurrents...
Va falloir que je cherche ailleurs l'origine du problème.
Pour le crashLog je suis obligé d'avouer que je ne sais pas où le trouver une fois qu'on a bêtement quitté Xcode ... il doivent bien être sauvegardés quelque part non ? ...(j'ai cherché du côté de library/log sans succès ...j'ai trouvé des tas de logs d'appli iPhones dans le dossier mobile)
Mais bon, déjà si ça vient pas de ressources partagées parce qu'immutables, j'ai plus qu'à revoir ma copie sur le code lui même de mes tâches.
MERCI ++ Mala & Zoc
La copy ne devrait rien apporter. (Le code en exemple contient un joli leak, [... copy] fabrique un objet avec un retain a 1) L'objet est immutable donc thread safe.
Un problème connu et documenté possible avec un tableau partagé entre plusieurs thread est si un thread retire du tableau un objet utilisé par un autre thread, l'objet est release dans le dos du second thread donc plantage. Mais ca ne devrait pas être ton cas si ton NSArray est bien un NSArray.
Ou alors le code de tes tâches a un soucis. Suivant ce que tu veux faire, tu peux peut être partitionner ton tableau et allouer un thread par partition comme ca personne ne se marche sur les pieds et ca t'evite trop de synchronized. Ce dernier point peut être critique si tu as des centaines de taches (voir http://cocoasamurai.blogspot.com/2008/04/osspinlock-lock-showdown-posix-locks-vs.html).
Enfin les crashlog sont dispos depuis l'appli "console" sous "User diagnostic reports"
Manu
Je crois en effet que c'est mon code qui a un problème.
C'est vrai que mon NSArray est en réalité récupéré en valeur de retour d'une méthode qui en fait renvoie un NSMutableArray.
Mais en aucun cas je ne tente de le modifier.
Sinon j'aurais un warning à ce sujet du reste puisque déclaré immutable, non ?
Euh, non.
La convention veut que toute méthode contenant "copy" dans son nom renvoie un objet avec un retainCount à 1.
Charge à la méthode faisant appel à de telles méthodes de le releaser
Ce que l'on fait sans problème quand on connait les naming conventions qui sont justement là pour ça.
Du reste, si on implémente une méthode quelconque contenant le mot "copy" en renvoyant un objet autoReleasé, l'analyseur de Clang nous rappelle à l'ordre immédiatement.
ainsi:
Et c'est même pour ça qu'il y a le terme copy dans le nom de la méthode
Dès qu'on touche aux threads, on peut facilement devenir parano.
Ce que tu dis est vrai en théorie, en pratique le problème peut venir de n'importe où.
(NSOperation contenait un bug sournois dans Léo, je ne sais s'il a été corrigé depuis)
Il y a quelques mois, j'ai posté un exemple de chargement d'images en multi threads.
Ca plantait régulièrement car j'étais en 10.4.0 à cause d'un bug sur NSImage, qui fut résolu avec la 10.4.3.
Avec les threads je fais confiance à personne ...
Grilled
Le compilateur renverrait même une erreur, il se base sur le type déclaré à la compilation et non a runtime.
As tu trouvé tes crashlog ?
Mais bien sûr !
Ah ! ben ça doit être à cause de ça que je trouve pas mes crashLogs!
J'ai pourtant fini par avoir le temps de chercher la piste de Manu du côté des "User diagnostic reports" de la console ... mais rien
C'est pénible ces crash capricieux non reproductibles, ... et pas moyen de faire crasher de nouveau mon projet.
Et ni Clang ni Instrument ne me pointent le moindre problème potentiel.
(quoique j'exploite surement pas Instrument au mieux de ses possibilités )
J'en viens à me demander si c'était pas le système et XCode qui étaient devenus instables à force de jamais éteindre ma machine sauf pour les mises à jour.
Faudra que j'attende le prochain crash pour aller plus loin dans l'analyse de ce crash et dans l'attente je vais tâcher de blinder tout ça au mieux.
Allez, Demain, il fera jour
PS: Qu c'est pénible ces titres de thread qui finissent tronqués à force d'être préfixés automatiquement par d'inutiles Re: Re: Re: Re: