IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

Sur la rapidité des IOstream


Sujet :

SL & STL C++

  1. #1
    Membre émérite

    Inscrit en
    mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut Sur la rapidité des IOstream
    Citation Envoyé par 3DArchi Voir le message
    Toute la mécanique des streambuffer est en virtuelle. C'est d'ailleurs là que se passe le principale de la gestion du flux (hors formatage) :
    Et c'est une catastrophe...
    Vous permettez que je rage un peu sur IOStream ? Cette partie du C++ m'irrite systématiquement à chaque fois que je veux l'utiliser.

    <RAGE>
    Je suis tombé récemment sur un post sur stack overflow qui résume bien la situation :
    Q : C++0X Concepts are gone. Which other features should go too?

    A:
    Of course, plenty of old C cruft could be ditched too, but recently, I've discovered that the one change I'd really love to see is...... ditching the Iostreams library. Toss it out, and build a new STL-style I/O library based on generic programming.

    The current OOP-styled Iostreams library is ugly, slow, overcomplicated and inflexible. There's too much voodoo involved in defining new streams, too few standard stream types involved, too little flexibility (the problem that made me realize how limited the library is, was that I needed to extract a float from a string. Easy to do with stringstream, but if you need to do it often, you don't want to have to copy the input string every time (as the stringstream does) -- where's the stream that works on an existing iterator range? Or a raw array, even?)

    Throw IOstreams out, develop a modern replacement, and C++ will be vastly improved.
    Amen.

    Je ne sais pas si vous avez déjà lu cette série de post déprimante par Raymond Chen (guru mircrosoft C/C++) et Rico Mariani (guru microsoft C#) ?
    Elle commence par Raymond Chen qui écrit une petite appli C++ assez simple - un dictionnaire chinois/anglais. Rico Mariani décide alors de réécrire cette appli ligne par ligne en C#. Et Les perfs de l'appli C# enfonce celle de l'appli C++ dans les grandes largeurs !! (x10 !). Quelques jours plus tard et plusieurs update plus tard, l'appli C++ de Raymond Chen finit par rattraper les perfs du C# mais il a du se taper de nombreuses passes d'optimisation et écrire du code bas-niveau de plus en plus horrible et de plus en plus long.

    Et pourquoi l'appli C++ originale donne des perfs aussi mer.... ?
    IOstream

    L'horreur est la suivante : Pour peupler le dictionnaire, il faut ouvrir un fichier texte encodé au format 950 (du chinois) et le lire ligne par ligne tout en convertissant chaque ligne en Unicode.
    Le code C++ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    std::wifstream src;
    src.imbue(std::locale(".950"));
    src.open("cedict.b5");
    wstring s;
    while (getline(src, s)) 
    {
       // do something
    }
    Le code C# :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    StreamReader src = new StreamReader(
                             "cedict.b5", 
                            System.Text.Encoding.GetEncoding(950));
    string s;
    while ((s = src.ReadLine()) != null)
    {
       // do something
    }
    Et bien c'est une boucherie.
    Ce code C# est x20 plus rapide chez moi. (VS2008)

    J'ai essayé d'analyser ce que fait respectivement chaque code et si je ne me suis pas trompé :

    Le code C# mappe le fichier en mémoire puis le parcours ligne par ligne, tout en convertissant chaque ligne en Unicode en appelant MultiByteToWideChar() sur la ligne entière.

    Le code C++ ouvre un flux, puis parcours le flux ligne par ligne et appelle pour chaque caractère la fonction de conversion vers l'Unicode codecvt::do_in, qui est bien évidement une fonction virtuelle qui ne s'inline pas, qui lock un mutex pour le fun, tout ça pour finalement appeler MultiByteToWideChar.... sur un seul caractère à la fois.
    </RAGE>

  2. #2
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2008
    Messages : 1 505
    Points : 2 798
    Points
    2 798
    Par défaut
    Pour en rajouter une couche sur les iostream, il y a quelque chose que je n'ai jamais compris non plus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (std::stringstream() << "toto" << 1 << "tutu").str()
    Ne compile pas, puisque operator<< sur un stringstream renvoie un ostream&...

    C++ a des type de retour covariants, pourquoi diable ne sont ils pas utilisés ?

  3. #3
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    je serais assez d'accord sur le fait que les iostreams sont un peu un rélent d'un passez sombre ou on ne pouvait pas faire bien mieux.

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Ne compile pas, puisque operator<< sur un stringstream renvoie un ostream&...

    C++ a des type de retour covariants, pourquoi diable ne sont ils pas utilisés ?
    Parce que operator << n'est pas une fonction virtuelle de ostream qui est surdéfinie dans les classes dérivées, tout simplement. Si je voulais récupérer un std::ostringstream& en retour d'un opérateur <<, il faudrait explicitement écrire cette version de l'opérateur avec ce type.

  5. #5
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2008
    Messages : 1 505
    Points : 2 798
    Points
    2 798
    Par défaut
    Parce que operator << n'est pas une fonction virtuelle de ostream qui est surdéfinie dans les classes dérivées, tout simplement. Si je voulais récupérer un std::ostringstream& en retour d'un opérateur <<, il faudrait explicitement écrire cette version de l'opérateur avec ce type.
    J'étais persuadé qu'operator<< était virtuelle. Mais cela dit, cela ne change pas le fait qu'il serait possible et pratique de fournir cet opérateur.

    L'absence d'une méthode générale simple pour concaténer des objets sans passer par une variable intermédiaire est une des choses qui me manque ( et (static_cast<std::stringstream&>(std::stringstream() << a << b << c).str() ) manque cruellement d'élégance...

    Les variadics template apporteront une solution, c'est sûr.

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    J'étais persuadé qu'operator<< était virtuelle
    En fait même si c'était le cas, la chaîne serait tout de même cassée lorsqu'on arriverait sur un opérateur << pour un type perso qu'on a écrit nous-même, et qui renverrait un std::ostream&.

    Mais cela dit, cela ne change pas le fait qu'il serait possible et pratique de fournir cet opérateur.
    Ca fait pas mal de boulot, d'écrire la même fonction avec tous les types dérivés possibles d'ostream

    L'absence d'une méthode générale simple pour concaténer des objets sans passer par une variable intermédiaire est une des choses qui me manque
    Ca manque en effet, mais ça s'implémente facilement. Comme tu le dis, le prochain standard devrait permettre d'avoir des trucs plus sympas à ce niveau.

  7. #7
    Expert éminent

    Inscrit en
    novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : novembre 2005
    Messages : 5 145
    Points : 6 863
    Points
    6 863
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Et c'est une catastrophe...
    Vous permettez que je rage un peu sur IOStream ?
    Je ne vois pas trop le rapport avec le sujet. Tu compares me semble-t'il deux conception tres OO des IO.

    J'ai essayé d'analyser ce que fait respectivement chaque code et si je ne me suis pas trompé :

    Le code C# mappe le fichier en mémoire puis le parcours ligne par ligne, tout en convertissant chaque ligne en Unicode en appelant MultiByteToWideChar() sur la ligne entière.

    Le code C++ ouvre un flux, puis parcours le flux ligne par ligne et appelle pour chaque caractère la fonction de conversion vers l'Unicode codecvt::do_in, qui est bien évidement une fonction virtuelle qui ne s'inline pas, qui lock un mutex pour le fun, tout ça pour finalement appeler MultiByteToWideChar.... sur un seul caractère à la fois.
    </RAGE>
    Qu'est-ce qui empeche l'implementation des IOStreams en C++ de faire la meme chose que l'implementation C#: rien. Le probleme que tu souleves c'est pas du aux IOStreams mais a l'implementation qui n'est pas, sur ce point, de la meme qualite que l'implementation C#.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  8. #8
    Expert éminent

    Inscrit en
    novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : novembre 2005
    Messages : 5 145
    Points : 6 863
    Points
    6 863
    Par défaut
    Citation Envoyé par Joel F Voir le message
    je serais assez d'accord sur le fait que les iostreams sont un peu un rélent d'un passez sombre ou on ne pouvait pas faire bien mieux.
    Je parie que meme en ayant vu les IOStream, la plupart des gens ne feraient pas mieux maintenant.

    Les locales -- et elles ont des interactions avec les IOStreams -- sont a mon avis bien plus contestables. Pour commencer, elles sont a moitie incomprehensibles, ensuite elles ont beaucoup moins bien vieilli.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  9. #9
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Je parie que meme en ayant vu les IOStream, la plupart des gens ne feraient pas mieux maintenant.

    Les locales -- et elles ont des interactions avec les IOStreams -- sont a mon avis bien plus contestables. Pour commencer, elles sont a moitie incomprehensibles, ensuite elles ont beaucoup moins bien vieilli.
    j'ai jamais dit le contraire
    et je suis relativzment tout a fait d'accord sur les locales :€

  10. #10
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2008
    Messages : 1 505
    Points : 2 798
    Points
    2 798
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Qu'est-ce qui empeche l'implementation des IOStreams en C++ de faire la meme chose que l'implementation C#: rien. Le probleme que tu souleves c'est pas du aux IOStreams mais a l'implementation qui n'est pas, sur ce point, de la meme qualite que l'implementation C#.
    Je ne suis pas totalement d'accord avec ton "rien". C# définit la locale une fois pour tout le fichier. C++ permet de changer la locale à tout moment sur le flux.

    Cette différence d'approche fait que C# peut faire facilement la conversion sur tout son buffer de lecture, là où une implémentation C++ ne peut pas faire cette optimisation (ou, au prix d'une beaucoup plus grande complexité d'implémentation) ==> une implémentation naïve fera la conversion au moment où la valeur est récupérée par l'utilisateur, pas au moment où elle est lue. Une implémentation qui voudrait faire mieux prend le risque de faire des centaines de conversions inutiles dans le cas défavorable d'un fichier multi-locales.

    Changer la locale au cours du parcours d'un fichier peut effectivement avoir un sens, dans le cas d'une déclaration xml ou d'une BOM. Mais c'est quelque chose qui ne sera effectué qu'une fois, et généralement on passera de "locale courante", donc pas de conversion à effectuer sur le flux, à "locale définie par le fichier" --> seule cette opération me semble nécessaire pour une librairie de flux standards, et ceci s'optimise beaucoup plus facilement que pouvoir changer à tout moment la locale.

  11. #11
    Expert éminent

    Inscrit en
    novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : novembre 2005
    Messages : 5 145
    Points : 6 863
    Points
    6 863
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Je ne suis pas totalement d'accord avec ton "rien". C# définit la locale une fois pour tout le fichier. C++ permet de changer la locale à tout moment sur le flux.

    Cette différence d'approche fait que C# peut faire facilement la conversion sur tout son buffer de lecture, là où une implémentation C++ ne peut pas faire cette optimisation (ou, au prix d'une beaucoup plus grande complexité d'implémentation).
    Tu me permettras de ne pas etre d'accord avec la complexite beaucoup plus grande. imbue dans l'implementation GNU fait une cinquante de lignes, dont au moins une quarantaine serait la meme si cette optimisation n'etait pas faite; il y a environ 5 lignes dans underflow qui traitent aussi ce cas. Ca fait au maximum 15 lignes ajoutees pour traiter le cas du changement de code pendant la lecture.

    Une implémentation qui voudrait faire mieux prend le risque de faire des centaines de conversions inutiles dans le cas défavorable d'un fichier multi-locales
    Si le fait de faire la conversion par bloc plutot que par caractere te fait gagner un x10 (j'ai pas ete voir si GNU mappait ou pas le fichier, l'optimisation sur la conversion est independante de cela), il faut souvent changer de codage pour que l'optimisation ne soit pas un gain net au final. (Sans compter que pour que ca coute il faut que la version encodee soit valable pour l'ancien code aussi).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #12
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2008
    Messages : 1 505
    Points : 2 798
    Points
    2 798
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Tu me permettras de ne pas etre d'accord avec la complexite beaucoup plus grande. imbue dans l'implementation GNU fait une cinquante de lignes, dont au moins une quarantaine serait la meme si cette optimisation n'etait pas faite; il y a environ 5 lignes dans underflow qui traitent aussi ce cas. Ca fait au maximum 15 lignes ajoutees pour traiter le cas du changement de code pendant la lecture.
    Oui, j'ai exagéré dans mon propos. Ce n'est pas non plus insurmontable, loin de là.

    Si le fait de faire la conversion par bloc plutot que par caractere te fait gagner un x10 (j'ai pas ete voir si GNU mappait ou pas le fichier, l'optimisation sur la conversion est independante de cela), il faut souvent changer de codage pour que l'optimisation ne soit pas un gain net au final. (Sans compter que pour que ca coute il faut que la version encodee soit valable pour l'ancien code aussi).
    Je ne suis pas sûr de comprendre ce que tu veux dire par là.

    Sinon, j'ai fait un test rapide, entre g++ et mono. g++ est environ deux fois plus rapide que mono pour la lecture d'un fichier utf-8 et conversion en wide char, ce qui confirme tes dires (mauvaise implémentation chez microsoft ?).

  13. #13
    Expert éminent

    Inscrit en
    novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : novembre 2005
    Messages : 5 145
    Points : 6 863
    Points
    6 863
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Oui, j'ai exagéré dans mon propos. Ce n'est pas non plus insurmontable, loin de là.
    On gagne tellement sur les lectures normales qu'il faudrait changer de locale tres souvent pour que ce qu'on perd lors de ce changement ne soit pas compense par ce qui est gagne lors des lecture.

    Sinon, j'ai fait un test rapide, entre g++ et mono. g++ est environ deux fois plus rapide que mono pour la lecture d'un fichier utf-8 et conversion en wide char, ce qui confirme tes dires (mauvaise implémentation chez microsoft ?).
    Mono n'est pas de MS que je sache (ou bien tu es sur qu'il a des perf comparable a l'implementation de MS?).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  14. #14
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2008
    Messages : 1 505
    Points : 2 798
    Points
    2 798
    Par défaut
    Mono n'est pas de MS que je sache (ou bien tu es sur qu'il a des perf comparable a l'implementation de MS?).
    Mono est réputé avoir de bonnes performances. Le fait que la lecture soit dans mon test deux fois plus lentes sous Mono que sous gcc est à mon avis suffisant pour mettre mon argument à la poubelle (je doute que Mono soit 20 fois plus lent que la CLR microsoft), et confirmer ce que tu disais à propos de défaut d'implémentation et non de conception.

  15. #15
    Invité
    Invité(e)
    Par défaut
    Quelques commentaires :

    1- toutes les implémentations des iostream ne sont pas égales... Sous windows, celle fournie avec STLPort est presque rapide, celle de la Dinkumware, même pas en rêve... C'est un truc à savoir quand on change de compilateur (ou même de version), si on change de STL au même moment, il peut arriver quelque chose d'affreux avec des iostream...

    2- toutes les iostream ne sont pas à jeter... les non formatées (read, write), il n'y a pas de souci, c'est propre et c'est portable.

    3- Les problèmes sont surtout en lecture formatée. Si on lit plus que quelques Ko, il vaut mieux oublier getline (et formater ses données en conséquence)

    4- si on a pas mal de choses à écrire et à lire, les bonnes méthodes sont presque toujours non portables, parce que la plupart des OS ont la gentillesse d'exposer des méthodes "internes" qui font ca très vite (chez windows, cela s'appelle les File Mappings).

    5- le plus amusant, c'est d'en avoir fait la méthode "officielle" de conversion de chaine en nombre et inversement... S'il y en a beaucoup, c'est une très mauvaise idée.

    Maintenant, pour tout ce qui n'est pas pressé (et tant qu'on ne rentre pas dans les détails) les iostream, ca reste assez facile d'emploi. C'est à mon avis leur seul avantage, mais il est de taille: ca arrive très souvent, et le code iostream est très facile à lire...

    Francois

  16. #16
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Discussion très intéressante. Ca me rappelle le post sur la rapidité des IOStreams.
    Personnellement, j'utilise quasiment que les écritures binaires (et même std::filebuf ). Franchement, avec filebuf, ça déménage grave.

  17. #17
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2004
    Messages : 1 717
    Points : 3 290
    Points
    3 290
    Par défaut
    Tiens, je connais pas std::filebuf O__O
    Je vais me renseigner. Ca apporte énormément de perf en écriturer ET en lecture?

  18. #18
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Citation Envoyé par Klaim Voir le message
    Tiens, je connais pas std::filebuf O__O
    Je vais me renseigner. Ca apporte énormément de perf en écriturer ET en lecture?
    Bah regarde les bench dans le lien que j'ai donné... Y'a pas photo !

  19. #19
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2004
    Messages : 1 717
    Points : 3 290
    Points
    3 290
    Par défaut
    O__O

    Ah ben merci alors j'avais raté le liens. Vais changer ma petite solution de log du coup...

    Au passage, il utilise quoi boost::log? J'ai lu dans la mailing list que le principal souci de perfs était au niveau de DateTime mais est-ce qu'il utilise aussi std::filebuf?

  20. #20
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Si je me souviens bien, (j'ai pas suivi de prêt la review) me semble que c'est du boost::format.


    edit : ouai non me suis gourré, c'est compatible avec boost::format...
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

Discussions similaires

  1. [JONAS][EJB]erreur sur la construction des EJB
    Par silvermoon dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 04/06/2004, 19h53
  2. Un peu de lumière sur l'arborescence des fichiers de Linux
    Par Noki dans le forum Administration système
    Réponses: 6
    Dernier message: 07/04/2004, 17h16
  3. question sur le format des images ..
    Par vbcasimir dans le forum Langages de programmation
    Réponses: 7
    Dernier message: 28/08/2003, 13h08
  4. Probleme sur le Fields des fichiers Xmlgram
    Par Sandrine75 dans le forum XMLRAD
    Réponses: 4
    Dernier message: 20/03/2003, 18h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo