59
Guillaume Laforge Groovy Project Manager SpringSource, a division of VMware Twitter: @glaforge Blog: http://glaforge.appspot.com Google+: http://gplus.to/glaforge PrettyTime et GPars

GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

Embed Size (px)

Citation preview

Page 1: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

Guillaume LaforgeGroovy Project ManagerSpringSource, a division of VMware

Twitter: @glaforgeBlog: http://glaforge.appspot.comGoogle+: http://gplus.to/glaforge

PrettyTime et GPars

Page 2: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 3: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 4: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

Nananère !

Page 5: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

PrettyTime

Ou comment écrire des dates relatives lisibles

Page 6: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 7: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 8: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 9: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 10: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 11: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 12: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 13: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 14: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

http://ocpsoft.com/prettytime/

Page 15: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

http://ocpsoft.com/prettytime/

2 days agoright now

3 months from nowin 3 minutes

Page 16: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 17: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 18: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 19: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 20: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge

Allez, des morceaux de code !

14

Page 21: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 22: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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}

Page 23: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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}

Page 24: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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>

Page 25: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 26: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 27: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

GPars

Ou comment tirer parti de vos multiples processeurs multicores

Page 28: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Page 29: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge

Loi de Moore

21

Page 30: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 31: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 32: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

Les programmes multithreadés d’aujourd’hui avec threads et locks marchent par accident :-)

Page 33: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

immuabilité passage demessages

Page 34: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

http://gpars.codehaus.org

Page 35: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 36: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 37: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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] }

Page 38: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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] }

Page 39: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge

Fonctions parallèles pour les collections

31

Page 40: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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()}

Page 41: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge

Map / filter / reduce

• Opérations sur les «parallel arrays» (JSR-266)

33

Page 42: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 43: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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) }}

Page 44: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge

Fork / join vs map / filter / reduce ?

36

Page 45: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 46: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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()

Page 47: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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()

Page 48: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 49: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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 }

Page 50: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 51: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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()

Page 52: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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()

Page 53: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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()

Page 54: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge

Oui mais en Java alors ?

43

Page 55: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 56: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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

Page 58: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

Q&A — Got questions, Really?

Page 59: GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge

@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