View
1.856
Download
2
Category
Preview:
Citation preview
Guillaume LaforgeGroovy Project ManagerSpringSource, a division of VMware
Twitter: @glaforgeBlog: http://glaforge.appspot.comGoogle+: http://gplus.to/glaforge
PrettyTime et GPars
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
2
Nananère !
PrettyTime
Ou comment écrire des dates relatives lisibles
http://ocpsoft.com/prettytime/
2 days agoright now
3 months from nowin 3 minutes
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
10
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
11
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Dépendance
• Si vous nʼavez pas de chance...
• Si vous avez de la chance...– dans un script Groovy
– ou avec Gradle
12
<dependency> <groupId>com.ocpsoft</groupId> <artifactId>ocpsoft-pretty-time</artifactId> <version>1.0.7</version></dependency>
dependencies { compile 'com.ocpsoft:ocpsoft-pretty-time:1.0.7'}
@Grab('com.ocpsoft:ocpsoft-pretty-time:1.0.7')import com.ocpsoft.pretty.time.PrettyTime
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Vie de cochon... cʼest bien ma veine...
13
C’est bien
mais ch’préfère utiliser
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Allez, des morceaux de code !
14
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Comment lʼutiliser ?
15
@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
Comment lʼutiliser ?
16
@Grab("com.ocpsoft:ocpsoft‐pretty‐time:1.0.7")import com.ocpsoft.pretty.time.PrettyTime long seconds = 1000long minutes = 60 * secondslong hours = 60 * minuteslong days = 24 * hourslong weeks = 7 * dayslong months = 31 * dayslong 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
Comment lʼutiliser ?
16
@Grab("com.ocpsoft:ocpsoft‐pretty‐time:1.0.7")import com.ocpsoft.pretty.time.PrettyTime long seconds = 1000long minutes = 60 * secondslong hours = 60 * minuteslong days = 24 * hourslong weeks = 7 * dayslong months = 31 * dayslong 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
Intégration
• PrettyTime sʼutilise facilement nʼimporte où...– utilisez simplement lʼAPI directement
• Mais PrettyTime propose une intégration JSF
• Il existe également un plugin Grails
17
<prettytime:display date="${someDate}" />
<h:outputText value="#{exampleBean.futureDate}"> <f:converter converterId="com.ocpsoft.PrettyTimeConverter"/></h:outputText>
GPars
Ou comment tirer parti de vos multiples processeurs multicores
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Loi de Moore
21
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
22
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
23
Les programmes multithreadés d’aujourd’hui avec threads et locks marchent par accident :-)
immuabilité passage demessages
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
27
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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)
28
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Fonctions parallèles pour les collections
29
@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
Fonctions parallèles pour les collections
30
@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
Fonctions parallèles pour les collections
31
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
32
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
Map / filter / reduce
• Opérations sur les «parallel arrays» (JSR-266)
33
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
34
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Fork / join
35
import static groovyx.gpars.GParsPool.runForkJoinimport 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
Fork / join vs map / filter / reduce ?
36
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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é
37
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Actors
38
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
Actors
38
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()
Verbes :start()stop()act()send(msg)sendAndWait(msg)actor << msgloop { }react { msg -> }react(timeout) { msg -> }msg.reply(msg2)receive()join()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
39
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Dataflow
40
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
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
41
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Agents
42
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
Agents
42
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
Agents
42
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
Oui mais en Java alors ?
43
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
44
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Comment choisir ?
45
mon problème
données tâches flux
linéaires récursives linéaires récursivesmêmes
donnéesrégulier irrégulier
collections parallèlesfork / join
fork / join fonctions asyncCSP
dataflow
fork / joinagentsSTM
dataflowstream
actors
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Thank you!
Guillaume Laforge
Head of Groovy Development
Email: glaforge@gmail.com
Twitter: @glaforge
Google+: http://gplus.to/glaforge
46
Q&A — Got questions, Really?
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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
•
48
Recommended