Advertisement
Advertisement

More Related Content

Advertisement

More from Guillaume Laforge(20)

Advertisement

GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

  1. PrettyTime et GPars Guillaume Laforge Groovy Project Manager SpringSource, a division of VMware Twitter: @glaforge Blog: http://glaforge.appspot.com Google+: http://gplus.to/glaforge
  2. Guillaume Laforge • Groovy Project Manager chez VMware • Initiateur du framework Grails • Créateur du toolkit Gaelyk pour App Engine • Co-auteur de Groovy in Action • Membre des CastCodeurs • Suivez-moi... ou pas :-) • Blog: http://glaforge.appspot.com • Twitter: @glaforge • Google+: http://gplus.to/glaforge @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 2
  3. Nananère !
  4. PrettyTime Ou comment écrire des dates relatives lisibles
  5. http://ocpsoft.com/prettytime/
  6. http://ocpsoft.com/prettytime/ 2 days ago right now 3 months from now in 3 minutes
  7. PrettyTime • Représenter des dates «relatives» – par rapport à «maintenant» • On souhaite savoir... – il y a combien de temps que... – dans combien de temps... • Plutôt que de connaître la date absolue et précise – du coup, meilleure notion de la fraîcheur dʼune information – surtout valable pour des laps de temps courts @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
  8. PrettyTime • Librairie Open Source : LGPL v3 • Version 1.0.7, disponible dans Maven Central • Léger : 58 ko • Développé par Lincoln III Baxter / OCPSoft – Senior Software Engineer chez JBoss / RedHat • Customisable – y-compris les langues supportées : • français, anglais, espagnol, allemand, italien, hollandais, portugais, bulgare, chinois, croate, estonien, hongrois, norvégien, polonais, roumain, slovénien, turque, vietnamien @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 11
  9. Dépendance • Si vous nʼavez pas de chance... <dependency> <groupId>com.ocpsoft</groupId> <artifactId>ocpsoft-pretty-time</artifactId> <version>1.0.7</version> </dependency> • Si vous avez de la chance... – dans un script Groovy @Grab('com.ocpsoft:ocpsoft-pretty-time:1.0.7') import com.ocpsoft.pretty.time.PrettyTime – ou avec Gradle dependencies { compile 'com.ocpsoft:ocpsoft-pretty-time:1.0.7' } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 12
  10. Vie de cochon... cʼest bien ma veine... C’est bien mais ch’préfère utiliser @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 13
  11. Allez, des morceaux de code ! @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 14
  12. Comment lʼutiliser ? @Grab("com.ocpsoft:ocpsoft‐pretty‐time:1.0.7") import com.ocpsoft.pretty.time.PrettyTime    def p = new PrettyTime() println p.format(new Date()) // à l'instant @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 15
  13. Comment lʼutiliser ? @Grab("com.ocpsoft:ocpsoft‐pretty‐time:1.0.7") import com.ocpsoft.pretty.time.PrettyTime   long seconds = 1000 long minutes =   60 * seconds long hours   =   60 * minutes long days    =   24 * hours long weeks   =    7 * days long months  =   31 * days long years   =  365 * days  long now = new Date().time def p = new PrettyTime() [     [  0,              "à l'instant"       ],     [ 10 * minutes,    "dans 10 minutes"   ],     [ ‐3 * hours,      "il y a 3 heures"   ],     [  9 * days,       "dans 1 semaine"    ],     [ ‐2 * weeks,      "il y a 2 semaines" ],     [  3 * months,     "dans 3 mois"       ],     [‐15 * years,      "il y a 1 décénie"  ],     [111 * years,      "dans 1 siècle"     ] ].each { diff, text ‐>     assert p.format(new Date(now + diff)) == text } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  14. Comment lʼutiliser ? @Grab("com.ocpsoft:ocpsoft‐pretty‐time:1.0.7") import com.ocpsoft.pretty.time.PrettyTime   long seconds = 1000 long minutes =   60 * seconds long hours   =   60 * minutes long days    =   24 * hours long weeks   =    7 * days long months  =   31 * days long years   =  365 * days  long now = new Date().time def p = new PrettyTime() [     [  0,              "à l'instant"       ],     [ 10 * minutes,    "dans 10 minutes"   ],     [ ‐3 * hours,      "il y a 3 heures"   ],     [  9 * days,       "dans 1 semaine"    ],     [ ‐2 * weeks,      "il y a 2 semaines" ],     [  3 * months,     "dans 3 mois"       ],     [‐15 * years,      "il y a 1 décénie"  ],     [111 * years,      "dans 1 siècle"     ] ].each { diff, text ‐>     assert p.format(new Date(now + diff)) == text } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  15. Intégration • PrettyTime sʼutilise facilement nʼimporte où... – utilisez simplement lʼAPI directement • Mais PrettyTime propose une intégration JSF <h:outputText value="#{exampleBean.futureDate}"> <f:converter converterId="com.ocpsoft.PrettyTimeConverter"/> </h:outputText> • Il existe également un plugin Grails <prettytime:display date="${someDate}" /> @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 17
  16. GPars Ou comment tirer parti de vos multiples processeurs multicores
  17. Loi de Moore @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 21
  18. Le constat... • Les architectures de nos ordinateurs évoluent – simple vers multi-processeurs (cʼest pas nouveau) – simple vers multi-coeurs • On atteints les limites de la loi de Moore • Nos applications devront évoluer pour sʼadapter – pour tirer parti des multiples coeurs et processeurs • Groovy se devait de proposer des solutions pour la programmation concurrente et parallèle @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 22
  19. Lʼâge de pierre • Il est difficile de bien utiliser – les threads – synchronize – wait / notify / notifyAll • On obtient rapidement – des dead-locks et live-locks – des race conditions – des starvation • Problème de gestion dʼaccès à de la mémoire partagée @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  20. Les programmes multithreadés d’aujourd’hui avec threads et locks marchent par accident :-)
  21. passage de immuabilité messages
  22. http://gpars.codehaus.org
  23. GPars • GPars est Open Source : Apache Software Licence 2 • Version actuelle : 0.12 • Dépendances – jsr166y et extra166y (1.7.0) – groovy, si vous lʼutilisez • GPars est bundlé avec la distribution de Groovy – mais peut-être téléchargé individuellement • Et surtout, GPars a une API Java ! – pas seulement pour Groovy @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 27
  24. Un large panel de solutions • actors • fork / join • map / filter / reduce avec parallel arrays • executors (java.util.concurrent) • dataflow (operators et streams) • agents • STM (Software Transactional Memory) • CSP (Communicating Sequential Processes) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 28
  25. Fonctions parallèles pour les collections @Grab('org.codehaus.gpars:gpars:0.12') import static groovyx.gpars.GParsPool.withPool def nums = 1..100000 withPool(5) { def squares = nums. collectParallel { it ** 2 }. grepParallel { it % 7 == it % 5 }. grepParallel { it % 3 == 0 } println squares[0..3] + "..." + squares[-3..-1] assert squares[0..3] == [36, 144, 1089, 1296] } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 29
  26. Fonctions parallèles pour les collections @Grab('org.codehaus.gpars:gpars:0.12') import static groovyx.gpars.GParsPool.withPool def nums = 1..100000 withPool(5) { def squares = nums.makeTransparent(). collect { it ** 2 }. grep { it % 7 == it % 5 }. grep { it % 3 == 0 } println squares[0..3] + "..." + squares[-3..-1] assert squares[0..3] == [36, 144, 1089, 1296] } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 30
  27. Fonctions parallèles pour les collections @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 31
  28. Map / filter / reduce • Concept popularisé par le papier de Google – approche utilisée initialement pour la création de lʼindex du moteur de recherche import static groovyx.gpars.GParsPool.withPool withPool(5) { def nums = 1..100000 println nums.parallel. map { it ** 2 }. filter { it % 7 == it % 5 }. filter { it % 3 == 0 }. reduce { a, b -> a + b } // sum() } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
  29. Map / filter / reduce • Opérations sur les «parallel arrays» (JSR-266) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 33
  30. Fork / join • Principe du « diviser pour mieux régner » – découper un problème en plus petits morceaux • Problématiques récursives – merge sort, quick sort – traverse de graphe – recherche sur un système de fichiers @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 34
  31. Fork / join import static groovyx.gpars.GParsPool.runForkJoin import static groovyx.gpars.GParsPool.withPool withPool { runForkJoin(new File("./src")) { currentDir -> long count = 0 currentDir.eachFile { if (it.isDirectory()) { println "Forking a thread for $it" forkOffChild it } else { count++ } } return count + childrenResults.sum(0) } } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 35
  32. Fork / join vs map / filter / reduce ? @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 36
  33. Actors • Concept popularisé par Erlang – repris aussi par Scala • Echange asynchrone de messages – au travers dʼune boîte aux lettres – coordination explicite • Pas dʼétat partagé @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 37
  34. Actors import static groovyx.gpars.actor.Actors.actor def decryptor = actor { loop { react { message -> if (message instanceof String) reply message.reverse() else stop() } } } def console = actor { decryptor.send 'lellarap si yvoorG' react { println 'Decrypted message: ' + it decryptor.send false } } [decryptor, console]*.join() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 38
  35. Actors import static groovyx.gpars.actor.Actors.actor def decryptor = actor { loop { react { message -> Verbes : if (message instanceof String) start() reply message.reverse() stop() else stop() act() } send(msg) } sendAndWait(msg) } actor << msg loop { } def console = actor { react { msg -> } decryptor.send 'lellarap si yvoorG' react(timeout) { msg -> } react { msg.reply(msg2) println 'Decrypted message: ' + it receive() decryptor.send false join() } } [decryptor, console]*.join() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 38
  36. Dataflow • Approche moins connue mais avec nombreux avantages – pas de « race conditions » – pas de « live locks » – des « deadlocks » déterministes • Tâches, utilisant des variables assignables une seule fois – possibilité dʼutiliser des «flux» pour des données en continu • Le dataflow gère le graphe des tâches à résoudre @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 39
  37. Dataflow import groovyx.gpars.dataflow.DataFlows import static groovyx.gpars.dataflow.DataFlow.task new DataFlows().with { task { a = 10 } task { b = 5 } task { x = a - b } task { y = a + b } task { result = x * y } assert 50 == result } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 40
  38. Agents • En anglais dans le texte (documentation de GPars) – a thread-safe non-blocking shared mutable state wrappers – thread-safe : utilisable par des threads concurrents – non-blocking : pas de «synchronized» et dʼattente pour accéder à la resource – shared mutable state : donnée partagée qui peut changer de valeur (non immuable) – wrapper : lʼagent est un wrapper autour de la donnée à manipuler • Concept inspiré par les « agents » de Clojure @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 41
  39. Agents import groovyx.gpars.agent.Agent def jugMembers = new Agent<List<String>>(['Me']) jugMembers.send { it << 'James'} def t1 = Thread.start { jugMembers.send { it << 'Joe' } } def t2 = Thread.start { jugMembers << { it << 'Dave' } jugMembers { it << 'Alice' } } [t1, t2]*.join() println jugMembers.val jugMembers.valAsync { println "Current members: $it" } jugMembers.await() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 42
  40. Agents import groovyx.gpars.agent.Agent def jugMembers = new Agent<List<String>>(['Me']) jugMembers.send { it << 'James'} def t1 = Thread.start { jugMembers.send { it << 'Joe' } } def t2 = Thread.start { jugMembers << { it << 'Dave' } jugMembers { it << 'Alice' } } [t1, t2]*.join() println jugMembers.val jugMembers.valAsync { println "Current members: $it" } jugMembers.await() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 42
  41. Agents import groovyx.gpars.agent.Agent def jugMembers = new Agent<List<String>>(['Me']) jugMembers.send { it << 'James'} def t1 = Thread.start { jugMembers.send { it << 'Joe' } } def t2 = Thread.start { jugMembers << { it << 'Dave' } jugMembers { it << 'Alice' } } [t1, t2]*.join() println jugMembers.val jugMembers.valAsync { println "Current members: $it" } jugMembers.await() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 42
  42. Oui mais en Java alors ? @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 43
  43. Comment choisir ? • Données – linéaires : collections parallèles – récursives : fork / join • Tâches – linéaires : fonctions asynchrones, CSP, dataflow, actors – recursives : fork / join – sur les mêmes données : agents, STM • Flux de données – régulier (même structure, même origine) : opérateurs dataflow – irrégulier (structures / origines différentes) : actors @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 44
  44. Comment choisir ? mon problème données tâches flux mêmes linéaires récursives linéaires récursives régulier irrégulier données collections agents fonctions async dataflow parallèles fork / join fork / join actors STM CSP stream fork / join dataflow @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 45
  45. Thank you! e L aforg pment aume vy Develo Guill Groo m Hea d of g mail.co aforge@ mail: gl glaforge e E @ o /glaforg T witter : http://gplus.t Go ogle+: @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 46
  46. Q&A — Got questions, Really?
  47. Image credits • Ecureuil: http://cheznectarine.c.h.pic.centerblog.net/a314fd6e.jpg • Didier: http://gallery.paperjam.lu/d/1316-2/IMG_3030.jpg • Cochon: http://chezginette.net.over-blog.net/pages/Connaitre_les_morceaux_de_viande-3441365.html • Petit cochon: http://www.renders-graphiques.fr/image/upload/normal/7471_render_cochon.png • Dépendance: http://www.komrod.com/wp-content/uploads/2011/02/internet-addiction-jeu-video-dependance1.jpg • Hexadecimal time: http://en.wikipedia.org/wiki/Hexadecimal_time • CPU: http://img.alibaba.com/wsphoto/v0/335090360/intel-xeon-3040-CPU-for-server.jpg • CPUs: http://blog.ldlc.com/wp-content/uploads/2010/02/comparatif-cpu.jpg • Loi de Moore: http://fr.wikipedia.org/wiki/Fichier:Loi_de_Moore.png • Biface: http://upload.wikimedia.org/wikipedia/commons/7/75/Biface.jpg • Car crash: http://www.twikeodream.com/images/2063798sub2.jpg • Mail box: http://images.neutralexistence.com/junkmail.jpg • Statue: http://www.linternaute.com/savoir/magazine/photo/tresors-de-kaboul/image/statue-228201.jpg • Diviser pour mieux régner: http://29.media.tumblr.com/tumblr_lppxk3FPiM1r0hgevo1_500.png • Grumpy 2: http://grumpy.division-par-zero.fr/wp-content/images/grumpy.jpg • @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 48
Advertisement