[GCD] NSOpérations: des conflits d'accès à  des "données en lecture seule" ?

ClicCoolClicCool Membre
décembre 2009 modifié dans API AppKit #1
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:
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

Réponses

  • mpergandmpergand Membre
    décembre 2009 modifié #2
    Salut,

    Moi je ferais un wrapper pour cet NSArray avec cette méthode:

    <br /><br />-(NSString*) copyOfStringAtIndex:(int) index<br />{<br />&nbsp; NSString* strCopy;<br /><br />&nbsp; @synchronized(self)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; srtCopy=[[theArray objectAtIndex:index] copy];<br />&nbsp; &nbsp; }<br /><br />&nbsp; return strCopy;<br />}<br />
    


    Si ça plante encore c'est que le problème est ailleurs  ;)

  • ClicCoolClicCool Membre
    22:02 modifié #3
    Ah oui, copier uniquement les strings à  la demande plutôt que tout l'array !

    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  :o
  • MalaMala Membre, Modérateur
    22:02 modifié #4
    dans 1260794816:

    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 ?

    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?
  • zoczoc Membre
    22:02 modifié #5
    Je suis aussi curieux de voir un crashlog...

    Parce que clairement, l'avantage des objets non mutables, c'est qu'ils ne posent justement pas de problèmes d'accès concurrents...
  • ClicCoolClicCool Membre
    22:02 modifié #6
    Vous me rassurez tous les deux.

    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  :o
  • manu57manu57 Membre
    22:02 modifié #7
    Salut,

    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
  • ClicCoolClicCool Membre
    22:02 modifié #8
    Merci 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 ?

    dans 1260818213:
    .../...(Le code en exemple contient un joli leak, [... copy] fabrique un objet avec un retain a 1) .../...

    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:
    • un [tt]copieDeStringAtIndex[/tt] DOIT renvoyer un objet autoreleasé.
    • un [tt]copyOfStringAtIndex[/tt] ou [tt]stringCopyAtIndex[/tt] ou tout autre méthode contenant "copy" DOIT renvoyer un objet avec un retain count à  1

  • mpergandmpergand Membre
    décembre 2009 modifié #9
    dans 1260818213:

    Salut,

    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.

    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 ...
  • ClicCoolClicCool Membre
    22:02 modifié #10
    dans 1260822181:
    .../...
    Et c'est même pour ça qu'il y a le terme copy dans le non de la méthode  ;)
    .../...


    Grilled  ;)
  • manu57manu57 Membre
    22:02 modifié #11
    Oui c'est juste. J'avais pas vu le nom de la méthode. (ma tournée ? )

    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 ?
  • ClicCoolClicCool Membre
    22:02 modifié #12
    Pas encore pu chercher mes crashlogs  :(



    dans 1260822557:
    .../...(ma tournée ? ) .../...


    :p Mais bien sûr !  :p
  • AliGatorAliGator Membre, Modérateur
    22:02 modifié #13
    Mais on va fiznir tsous bzourrés avec vous nourtés négérales dorbel :p
  • ClicCoolClicCool Membre
    décembre 2009 modifié #14
    dans 1260823411:

    Mais on va fiznir tsous bzourrés avec vous nourtés négérales dorbel :p


    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,  :p Demain, il fera jour  :p


    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:  >:)
  • AliGatorAliGator Membre, Modérateur
    22:02 modifié #15
    dans 1260832080:
    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:  >:)
    Ouais, vivement une mise à  jour de PommeDev ::)
Connectez-vous ou Inscrivez-vous pour répondre.