3. www.cetic.be
Le problème
• Solutions pour améliorer l’IO
• SSD ou HDD strippé, agrégation de bande passante
• Pruning des données sur disque, format de fichier performant en
termes d’IO (cf Parquet)
• Dans de nombreux cas, la performance est limitée par la charge de calcul.
• Gestion de la mémoire gourmande en CPU
• Sérialisation/Désérialisation
• Garbage Collector
3
4. www.cetic.be
Apport de Tungsten: Gestion de la mémoire
• Système de pagination en RAM
• Suppression du système d’objets de la JVM
• Compactage des données
• Transformation des traitements pour travailler sur les données brutes
4
5. www.cetic.be
Apport de Tungsten: Gestion de la mémoire
• Système de pagination en RAM
• Suppression du système d’objets de la JVM
• Compactage des données
• Transformation des traitements pour travailler sur les données brutes
4
6. www.cetic.be
Apport de Tungsten: Gestion de la mémoire
• Système de pagination en RAM
• Suppression du système d’objets de la JVM
• Compactage des données
• Transformation des traitements pour travailler sur les données brutes
4
5 objets Java
Indirections
en-tête d’objet: 12 octets
char[]: 20 octets d’en-tête + 10 octets de texte
hashcode: 8 octets
total: 50 octets pour 5 caractères
7. www.cetic.be
Apport de Tungsten: Gestion de la mémoire
• Système de pagination en RAM
• Suppression du système d’objets de la JVM
• Compactage des données
• Transformation des traitements pour travailler sur les données brutes
4
5 objets Java
Indirections
en-tête d’objet: 12 octets
char[]: 20 octets d’en-tête + 10 octets de texte
hashcode: 8 octets
total: 50 octets pour 5 caractères
8. www.cetic.be
Apport de Tungsten: Gestion de la mémoire
• L’évaluation d’expressions arbitraires est très coûteuse pour la JVM
• Dispatching de fonctions polymorphes
• Comportement variable en fonction du type des objets manipulés
• Boxing/Unboxing: overhead en temps et en mémoire
• Écriture inutile en mémoire des résultats intermédiaires
5
9. www.cetic.be
Apport de Tungsten: Gestion de la mémoire
• L’évaluation d’expressions arbitraires est très coûteuse pour la JVM
• Dispatching de fonctions polymorphes
• Comportement variable en fonction du type des objets manipulés
• Boxing/Unboxing: overhead en temps et en mémoire
• Écriture inutile en mémoire des résultats intermédiaires
5
• Réponse : Évaluation des
expressions, génération de
(byte)code ad hoc qui
supprime ces étapes
intermédiaires. ie, compilation
des expressions.
• Backends: JVM, LLVM, GPU, …
Temps
(sec)
0
10
20
30
40
Interprété Code généré Manuel
9,33
9,36
36,65
10. www.cetic.be
Pour aller plus loin
• https://spoddutur.github.io/spark-notes/
second_generation_tungsten_engine.html
• https://jaceklaskowski.gitbooks.io/mastering-spark-sql/spark-sql-
tungsten.html
• https://www.slideshare.net/SparkSummit/deep-dive-into-project-
tungsten-josh-rosen
6
12. www.cetic.be
Le problème
• Spark introduit des APIs de plus en plus abstraites: Dataframe/
Dataset, SQL, … : Structured APIs
• Objectif: expression plus aisée des traitements, même API pour
le batch et le streaming
8
13. www.cetic.be
Le problème
• Spark introduit des APIs de plus en plus abstraites: Dataframe/
Dataset, SQL, … : Structured APIs
• Objectif: expression plus aisée des traitements, même API pour
le batch et le streaming
8
data .map { case (dpt, age) => dpt -> (age, 1) }
.reduceByKey { case ((a1, c1), (a2, c2)) => (a1 + a2, c1 + c2) }
.map { case (dpt, (age, c)) => dpt -> age / c }
RDD
14. www.cetic.be
Le problème
• Spark introduit des APIs de plus en plus abstraites: Dataframe/
Dataset, SQL, … : Structured APIs
• Objectif: expression plus aisée des traitements, même API pour
le batch et le streaming
8
data .map { case (dpt, age) => dpt -> (age, 1) }
.reduceByKey { case ((a1, c1), (a2, c2)) => (a1 + a2, c1 + c2) }
.map { case (dpt, (age, c)) => dpt -> age / c }
RDD
data.groupBy(‘’dept’’).avg(‘’age’’)
select dept, avg(age) from data group by dept
DataFrame
SQL
15. www.cetic.be
Le problème
• Il faut convertir une transformation exprimée en Structured API en
un plan d’actions exécutable.
• Le plan doit être exécuté par les workers sous la supervision du
driver.
• Plusieurs plans peuvent concrétiser une transformation. Il faut
donc choisir le meilleur plan.
• Réponse: Catalyst optimise la manière de transformer un
traitement abstrait en plan d’actions exécutable.
9
21. www.cetic.be
Étape 1 : Exemple de règle de transformation
1 + 2 + t1.value
Add
Add
Literal(1) Literal(2)
Attribute(t1.value)
22. www.cetic.be
Étape 1 : Exemple de règle de transformation
1 + 2 + t1.value
Add
Add
Literal(1) Literal(2)
Attribute(t1.value)
Évalué à chaque ligne
23. www.cetic.be
Étape 1 : Exemple de règle de transformation
1 + 2 + t1.value
Add
Add
Literal(1) Literal(2)
Attribute(t1.value)
Évalué à chaque ligne
Add(Literal(x), Literal(y)) ! Literal(x+y)
24. www.cetic.be
Étape 1 : Exemple de règle de transformation
1 + 2 + t1.value
Add
Add
Literal(1) Literal(2)
Attribute(t1.value)
Évalué à chaque ligne
Add(Literal(x), Literal(y)) ! Literal(x+y)
Add
Literal(3) Attribute(t1.value)
25. www.cetic.be
Étape 1 : Exemple de règle de transformation
1 + 2 + t1.value
Add
Add
Literal(1) Literal(2)
Attribute(t1.value)
Évalué à chaque ligne
Add(Literal(x), Literal(y)) ! Literal(x+y)
Add
Literal(3) Attribute(t1.value)
Évalué une seule fois
26. www.cetic.be
Étape 2 : planification physique & génération de code
12
Plan logique
optimisé
27. www.cetic.be
Étape 2 : planification physique & génération de code
12
Plan logique
optimisé
Plan physique 1
Plan physique 2
…
Génération de plans: lecture des
sources, predicate pushdown,
utilisation de cache, pipelining de
projection et de filtres, …
28. www.cetic.be
Étape 2 : planification physique & génération de code
12
Plan logique
optimisé
Plan physique 1
Plan physique 2
…
Génération de plans: lecture des
sources, predicate pushdown,
utilisation de cache, pipelining de
projection et de filtres, …
Plan physique
sélectionné
Stratégies + Règles + Modèle de
coûts exploitant les statistiques
des sources
29. www.cetic.be
Étape 2 : planification physique & génération de code
12
Plan logique
optimisé
Plan physique 1
Plan physique 2
…
Génération de plans: lecture des
sources, predicate pushdown,
utilisation de cache, pipelining de
projection et de filtres, …
Plan physique
sélectionné
Stratégies + Règles + Modèle de
coûts exploitant les statistiques
des sources
DAG de RDDs
30. www.cetic.be
Étape 2 : Exemple de planification physique
13
val joined = users.join(events, users.id == events.uid)
31. www.cetic.be
Étape 2 : Exemple de planification physique
13
val joined = users.join(events, users.id == events.uid)
Join
users events
Plan logique
32. www.cetic.be
Étape 2 : Exemple de planification physique
13
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
users events
[users trié par id] [events trié par uid]
Join
users events
Plan logique
33. www.cetic.be
Étape 2 : Exemple de planification physique
13
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
users events
[users trié par id] [events trié par uid]
34. www.cetic.be
Étape 2 : Exemple de planification physique
14
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
users events
[users trié par id] [events trié par uid]
35. www.cetic.be
Étape 2 : Exemple de planification physique
14
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
users events
[users trié par id] [events trié par uid]
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
users events
36. www.cetic.be
Étape 2 : Exemple de planification physique
14
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
users events
37. www.cetic.be
Étape 2 : Exemple de planification physique
15
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
users events
38. www.cetic.be
Étape 2 : Exemple de planification physique
15
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
users events
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
ScanParquet
(trié par id)
ScanTable
39. www.cetic.be
Étape 2 : Exemple de planification physique
15
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
ScanParquet
(trié par id)
ScanTable
40. www.cetic.be
Étape 2 : Exemple de planification physique
16
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
ScanParquet
(trié par id)
ScanTable
41. www.cetic.be
Étape 2 : Exemple de planification physique
16
val joined = users.join(events, users.id == events.uid)
Sort-Merge join
[users.id = events.uid]
Sort
[users.id]
Sort
[events.uid]
ScanParquet
(trié par id)
ScanTable
Sort-Merge join
[users.id = events.uid]
Sort
[events.uid]
ScanParquet
(trié par id)
ScanTable
42. www.cetic.be
Pour aller plus loin
• https://databricks.com/glossary/catalyst-optimizer
• https://www.youtube.com/watch?v=RmUn5vHlevc
• https://databricks.com/blog/2015/04/13/deep-dive-into-spark-
sqls-catalyst-optimizer.html
• https://data-flair.training/blogs/spark-sql-optimization/
• https://developer.ibm.com/code/2017/11/30/learn-extension-
points-apache-spark-extend-spark-catalyst-optimizer/
17
43. www.cetic.be
La suite du programme: Spark Hands-On
Où vous
• Réaliserez vos premiers pas avec Spark
• Traquerez sans pitié des orphelins
• Développerez un modèle prédictif avec Dwayne Johnson
18