Hadoop performances
YOUR HUMBLE PRESENTER
Sofian DJAMAA
• Ex-consultant OCTO
#expert-performance
#expert-NoSQL
#expert-babyfoot
• Co-fondateur du PerfUG
#performance
#presentations #usi #devoxxfr
• Développeur Hadoop @ Criteo
• Amateur de films de requins
#avalanche-shark
#sharknado
#mega-shark-vs-giant-octopus
#sharktopus
2
QU’EST-CE QU’HADOOP?
• Stockage: HDFS
– Haute disponibilité
– Large volumétrie
• Traitement: MapReduce
– Divide & conquer
– Parallélisation sur des grosses volumétries (>> PB)
• Stockage + Traitement = « Big Data »
3Copyright © 2013 Criteo.
ADAPTER LA CONFIGURATION DU CLUSTER
Le plus simple est dans un premier temps de configurer correctement son cluster Hadoop !
• Eviter les accès disques lents sur les datanodes et les tasktrackers
• RAID
• NAS
• LVM
• Un VLAN dédié au cluster pour éviter les problèmes de réseau
• Un ensemble de machines locales dédiées à Hadoop est l’idéal
• Les machines servant au MR doivent être homogènes au niveau hardware (pour une meilleure parallélisation)
Monitorer l’usage CPU, RAM et les I/O (disques et réseau) via des outils de monitoring
Beaucoup de littérature disponible sur les tailles de machines
Terasort to tune the cluster :)
4
MAP REDUCE
5
MAP REDUCE
6
MAP REDUCE
7
PHASE MAP
• Les fichiers d’entrée sont contenus dans des « input
splits »
• Chaque fichier est assigné à un mapper
• Le mapper effectue la tâche assignée (job)
• Les résultats sont stockés dans un buffer mémoire
temporaire
• Les résultats sont ensuite partitionnés, triés et écrits sur
disque
• Les fichiers sont ensuite envoyés aux reducers
8
PHASE MAP: OPTIMISER LA LECTURE DES FICHIERS
TAILLE DES BLOCKS
• Les fichiers d’entrée sont stockés sur HDFS dans des blocks
– Chaque fichier est séparé en input split
– Chaque input split est stocké dans 1 ou plusieurs blocks
• En général, un input split est assigné à un mapper
taille de l’input d’un mapper = taille du fichier / facteur de compression
Considérations de performance :
• Si les input splits sont plus grands que les blocks HDFS : I/O réseau
pour récupérer d’autres blocs sur d’autres DataNodes
• Si les input splits sont plus petits que les blocks HDFS :
fragmentation
• Si les input splits sont trop petits : trop de mappers alloués pour des
petites tâches (overhead de création des mappers)
• dfs.block.size est un paramètre global au cluster !
9
PHASE MAP: OPTIMISER LA LECTURE DES FICHIERS
COMPRESSION
Rappel:
• taille de l’input d’un mapper = taille du fichier / facteur de compression
• Il existe plusieurs formats de compression utilisables dans Hadoop:
– GZIP : utilise le moins de mémoire mais le plus de CPU et n’est pas splittable
– LZO : propose la taille de compression la plus optimale mais gourmand en CPU et mémoire
– Snappy : est le plus rapide mais moins efficient que LZO sur la taille de compression
• Principes généraux des algorithmes de compression
– Algorithmes sans perte
• Utilisation de la redondance : deflate (remplacement de symboles, utilisation de pointeurs), compression par dictionnaire
(stockage d’occurrences à remplacer par un indice)…
– Algorithmes avec perte : JPEG
• Le curseur est à placer entre les ressources du cluster (CPU, I/Os, RAM…) et la taille des input splits :
monitoring !
• Il est possible de combiner la compression à la sérialisation des données : Avro, ProtoBuf, Thrift
10
PHASE MAP: OPTIMISER LA LECTURE DES FICHIERS
FORMATS DE FICHIER
• Les fichiers d’entrée sont stockés selon un format :
– Texte (plain, CSV, TSV, JSON…)
– Binaire KV (SequenceFile)
– Binaire Columnar (RCFile, Parquet, ORC)
• taille input record en mémoire = taille de l’input record stocké sur HDFS/
“largeur” du tuple d’entrée
• Pour optimiser la mémoire et le CPU il est possible de ne récupérer qu’un sous-
ensemble des records stockés sur les DataNode : format columnar
• Il existe plusieurs formats columnar :
– RCFile
– Parquet
– ORCFile
• Plus d’informations sur ma présentation au dernier meetup ParisDataGeek 
11
PHASE MAP: OPTIMISER LA COLLECTE DES
DONNÉES TRAITÉES
• Lorsque les données ont été traitées par la fonction map,
elles sont stockées dans un buffer temporaire avant
d’être écrites sur disque
– Les données sur disque doivent être préparées pour les
reducers : partitionnées, triées et potentiellement compressées.
– Pour éviter des I/O inutiles, ces traitements se font en mémoire
• Si le buffer est trop petit pour recevoir l’ensemble du
dataset, les données sont flushées partiellement sur le
disque
– Selon un ratio : io.sort.factor=10
– Selon la taille du buffer : io.sort.mb=256
• Solutions
– Augmenter la taille du buffer
– Réduire le ratio des meta-data
– Augmenter le nombre de mappers
• Ces paramètres sont à modifier suite à l’exécution de vos
jobs
12
SPILLING EN DÉTAIL
• En réalité le Spilling est un
Partition/Sort/Merge sur disque 
13
PHASE MAP: OPTIMISER L’ENVOI DES
DONNÉES AUX REDUCERS
• Compression
– mapred.compress.map.output : spécifier si les fichiers intermédiaires, résultats de
map, doivent être compressés.
• Combiners
– Lorsque les mappers ont traité les différents tuples, les résultats sont stockés en
mémoire avant d’être écrits sur disque
– En prenant pour exemple « WordCount », les mappers ne génèrent qu’une série de
tuples du type (« clef » -> 1), (« clef » -> 1), (« clef » -> 1)…
– Si la clef en question est présente de nombreuses fois, le tuple est dupliqué et la taille
(et le nombre) des fichiers augmentent  impact sur les I/O réseau
– Solution : utiliser un combiner
• Peut être la fonction reduce (dans le cas de WordCount)
• Ou un autre aggrégat
• Partitionnement
– Pour que les reducers puissent traiter des données de manière performante
(algorithmes linéaires), les données sont triées et partitionnées par clef aux reducers
– Il est donc important de choisir sa clef de partitionnement afin d’avoir une distribution
uniforme des données aux reducers
• Des reducers ou mappers en wait = des ressources bloquées sur le cluster =
des jobs en retard !!!!!
• REDUIRE LES I/O
14
PHASE REDUCE
• Les fichiers d’entrées sont partitionnés pour les reducers
– Une clef est assignée à chaque reducer (pour travailler avec des fichiers
provenant de différents mappers)
– C’est pour cela que les combiners et la compression de fichiers sont
importants : ils permettent de réduire le trafic réseau
Etapes :
• Shuffle : récupérer les fichiers produits par les mappers (en réalité
c’est ce sens là)
• Merge : fusionner les fichiers d’entrée déjà triés afin de produire
l’ensemble de données d’entrée
• Reduce : appliquer la fonction de réduction (ex : group by,
somme, moyenne…)
• Write : écrire les résultats finaux sur disque
15
PHASE REDUCE : OPTIMISER LA LECTURE DES
FICHIERS D’ENTRÉE
• Les fichiers d’entrée sont récupérés depuis les emplacements
locaux aux mappers  charge réseau à prévoir
– Combiners
– Compression
– Partitionnement
• Pour accélérer la récupération des fichiers pouvant être sur
plusieurs mappers (donc machines) différents : multithreading
16
PHASE REDUCE : OPTIMISER LE MERGE DES
FICHIERS D’ENTRÉE
• Les fichiers d’entrée sont récupérés et lus par le reducer
• Chaque input est traitée
– Soit en mémoire si le dataset tient
– Soit sur disque si le dataset est supérieur
• Les fichiers sont lus de telle manière à garder l’ordre afin
d’appliquer la fonction de reduce de manière linéaire (Big-O(n))
• De la même manière que lors de l’étape de map, le reducer peut
faire du spilling
– Lorsque la mémoire est trop chargée, les données sont flushées sur
disque et mergées entre elles
• Pour éviter le spilling : io.sort.factor
17
PHASE REDUCE : OPTIMISER L’ECRITURE DES
FICHIERS FINAUX
• Partition key (distribute by xxx in Hive)
– pour les reducers
• Car les data sont distribuées par clefs dans les reducers
– si un reducer travaille sur plusieurs partitions
• plusieurs RecordWriters  problème de performance
• L’idée est donc de dédier les reducer à l’écriture sur une seule
partition
18
TUNING JVM
• Réutiliser la JVM
– Temps d’initialisation de la JVM à prendre en compte
• Heap
• JIT
• …
• Heap management
– Dimensionner correctement la heap
• Attention au GC
19
OPTIMISATIONS HIVE/CASCADING
• Mapjoins/Hashjoins :
– S’assurer que l’ensemble utilisé pour la jointure tient effectivement en mémoire
• UNION ALL/GROUP BY plutôt que d’utiliser des LEFT JOIN : moins de jobs générés
– Hive peut lancer plusieurs jobs pour une requête
• Sacrifier le temps d’exécution d’un job pour améliorer le temps de requêtage dans Hive
20
RAPPEL
21
mapred.min.split.size
mapred.max.split.size
dfs.block.size (cluster wide)
hive.merge.mapredfiles
hive.merge.smallfiles.avgsize
+ compression
+ input format
mapred.compress.map.output
io.sort.mb
io.sort.splill.percent
io.sort.factor
mapred.combiner.class
mapred.reduce.parallel.copies
mapred.reduce.child.java.optsmapred.map.child.java.opts
CLUSTER MANAGEMENT
MRV1
• Utiliser des pools de jobs
22
CLUSTER MANAGEMENT
YARN
• La partie stockage ne bouge pas mais le
JobTracker disparaît au profit d’une nouvelle
architecture
Composants :
• Resource Manager
• Application Manager
• Scheduler
• Embarqué dans Hadoop 2
– Possibilité de l’utiliser hors d’Hadoop mais quelques
fonctions sont manquantes (ex : API de communication
avec les executors)
23
CLUSTER MANAGEMENT
APACHE MESOS
• « Resource offer » : CPU, RAM…
• Le master Mesos propose une quantité de
ressources à un framework à exécuter en fonction
de :
– Politiques d’organisation
– Fair scheduling
– Priorité
• Il est aussi possible d’étendre via plugins (à
développer) le système de mise à disponibilité de
ressources
• Côté développeur : définir les tasks et leurs
ressources nécessaire pour le framework scheduler
– API : JAVA/Scala, Python, C++…
• Utilisable avec Hadoop mais aussi avec n’importe
quel type de frameworks (ex : Spark)
24
LE PLUS IMPORTANT : LE
MONITORING/PROFILING
• JobTracker
– Possibilité de définir ses propres compteurs pour
debug
• Ganglia
• Nagios/Centreon : monitoring bas niveau (CPU,
RAM, I/O disque, I/O réseau…)
• Starfish : optimisation de la configuration
Hadoop (ex : mapred-site.xml) après analyse
des logs de jobs
25
PETITS CONSEILS
• Si vos data tiennent en RAM… EVITEZ HADOOP !!!!
• Si vos data peuvent tenir en RAM sur peu de machines… EVITEZ HADOOP
– Spark
– Gigaspaces (lol… go Spark)
• En gros… tant que vous pouvez, évitez Hadoop 
• Pour des requêtes qui ne prennent que peu de temps, évitez de lancer des jobs MR ou Hive ou autre…
– Le temps d’initialisation des mappers et reducers est très long…
• Et surtout : ME-SU-REZ !!!!
– Il est très difficile d’anticiper les paramètres de configuration du cluster
– Chaque job est différent si le dataset d’entrée n’est pas le même (ou si le job créé des data supplémentaires, cf. EXPLODE)
26
QUESTIONS ?
We can talk about…
#hadoop
27
#scalding
#scala#sharks
#summingbird
#performance
#mechanical-sympathy
#hive #cascading
#JVM

PerfUG - Hadoop Performances

  • 1.
  • 2.
    YOUR HUMBLE PRESENTER SofianDJAMAA • Ex-consultant OCTO #expert-performance #expert-NoSQL #expert-babyfoot • Co-fondateur du PerfUG #performance #presentations #usi #devoxxfr • Développeur Hadoop @ Criteo • Amateur de films de requins #avalanche-shark #sharknado #mega-shark-vs-giant-octopus #sharktopus 2
  • 3.
    QU’EST-CE QU’HADOOP? • Stockage:HDFS – Haute disponibilité – Large volumétrie • Traitement: MapReduce – Divide & conquer – Parallélisation sur des grosses volumétries (>> PB) • Stockage + Traitement = « Big Data » 3Copyright © 2013 Criteo.
  • 4.
    ADAPTER LA CONFIGURATIONDU CLUSTER Le plus simple est dans un premier temps de configurer correctement son cluster Hadoop ! • Eviter les accès disques lents sur les datanodes et les tasktrackers • RAID • NAS • LVM • Un VLAN dédié au cluster pour éviter les problèmes de réseau • Un ensemble de machines locales dédiées à Hadoop est l’idéal • Les machines servant au MR doivent être homogènes au niveau hardware (pour une meilleure parallélisation) Monitorer l’usage CPU, RAM et les I/O (disques et réseau) via des outils de monitoring Beaucoup de littérature disponible sur les tailles de machines Terasort to tune the cluster :) 4
  • 5.
  • 6.
  • 7.
  • 8.
    PHASE MAP • Lesfichiers d’entrée sont contenus dans des « input splits » • Chaque fichier est assigné à un mapper • Le mapper effectue la tâche assignée (job) • Les résultats sont stockés dans un buffer mémoire temporaire • Les résultats sont ensuite partitionnés, triés et écrits sur disque • Les fichiers sont ensuite envoyés aux reducers 8
  • 9.
    PHASE MAP: OPTIMISERLA LECTURE DES FICHIERS TAILLE DES BLOCKS • Les fichiers d’entrée sont stockés sur HDFS dans des blocks – Chaque fichier est séparé en input split – Chaque input split est stocké dans 1 ou plusieurs blocks • En général, un input split est assigné à un mapper taille de l’input d’un mapper = taille du fichier / facteur de compression Considérations de performance : • Si les input splits sont plus grands que les blocks HDFS : I/O réseau pour récupérer d’autres blocs sur d’autres DataNodes • Si les input splits sont plus petits que les blocks HDFS : fragmentation • Si les input splits sont trop petits : trop de mappers alloués pour des petites tâches (overhead de création des mappers) • dfs.block.size est un paramètre global au cluster ! 9
  • 10.
    PHASE MAP: OPTIMISERLA LECTURE DES FICHIERS COMPRESSION Rappel: • taille de l’input d’un mapper = taille du fichier / facteur de compression • Il existe plusieurs formats de compression utilisables dans Hadoop: – GZIP : utilise le moins de mémoire mais le plus de CPU et n’est pas splittable – LZO : propose la taille de compression la plus optimale mais gourmand en CPU et mémoire – Snappy : est le plus rapide mais moins efficient que LZO sur la taille de compression • Principes généraux des algorithmes de compression – Algorithmes sans perte • Utilisation de la redondance : deflate (remplacement de symboles, utilisation de pointeurs), compression par dictionnaire (stockage d’occurrences à remplacer par un indice)… – Algorithmes avec perte : JPEG • Le curseur est à placer entre les ressources du cluster (CPU, I/Os, RAM…) et la taille des input splits : monitoring ! • Il est possible de combiner la compression à la sérialisation des données : Avro, ProtoBuf, Thrift 10
  • 11.
    PHASE MAP: OPTIMISERLA LECTURE DES FICHIERS FORMATS DE FICHIER • Les fichiers d’entrée sont stockés selon un format : – Texte (plain, CSV, TSV, JSON…) – Binaire KV (SequenceFile) – Binaire Columnar (RCFile, Parquet, ORC) • taille input record en mémoire = taille de l’input record stocké sur HDFS/ “largeur” du tuple d’entrée • Pour optimiser la mémoire et le CPU il est possible de ne récupérer qu’un sous- ensemble des records stockés sur les DataNode : format columnar • Il existe plusieurs formats columnar : – RCFile – Parquet – ORCFile • Plus d’informations sur ma présentation au dernier meetup ParisDataGeek  11
  • 12.
    PHASE MAP: OPTIMISERLA COLLECTE DES DONNÉES TRAITÉES • Lorsque les données ont été traitées par la fonction map, elles sont stockées dans un buffer temporaire avant d’être écrites sur disque – Les données sur disque doivent être préparées pour les reducers : partitionnées, triées et potentiellement compressées. – Pour éviter des I/O inutiles, ces traitements se font en mémoire • Si le buffer est trop petit pour recevoir l’ensemble du dataset, les données sont flushées partiellement sur le disque – Selon un ratio : io.sort.factor=10 – Selon la taille du buffer : io.sort.mb=256 • Solutions – Augmenter la taille du buffer – Réduire le ratio des meta-data – Augmenter le nombre de mappers • Ces paramètres sont à modifier suite à l’exécution de vos jobs 12
  • 13.
    SPILLING EN DÉTAIL •En réalité le Spilling est un Partition/Sort/Merge sur disque  13
  • 14.
    PHASE MAP: OPTIMISERL’ENVOI DES DONNÉES AUX REDUCERS • Compression – mapred.compress.map.output : spécifier si les fichiers intermédiaires, résultats de map, doivent être compressés. • Combiners – Lorsque les mappers ont traité les différents tuples, les résultats sont stockés en mémoire avant d’être écrits sur disque – En prenant pour exemple « WordCount », les mappers ne génèrent qu’une série de tuples du type (« clef » -> 1), (« clef » -> 1), (« clef » -> 1)… – Si la clef en question est présente de nombreuses fois, le tuple est dupliqué et la taille (et le nombre) des fichiers augmentent  impact sur les I/O réseau – Solution : utiliser un combiner • Peut être la fonction reduce (dans le cas de WordCount) • Ou un autre aggrégat • Partitionnement – Pour que les reducers puissent traiter des données de manière performante (algorithmes linéaires), les données sont triées et partitionnées par clef aux reducers – Il est donc important de choisir sa clef de partitionnement afin d’avoir une distribution uniforme des données aux reducers • Des reducers ou mappers en wait = des ressources bloquées sur le cluster = des jobs en retard !!!!! • REDUIRE LES I/O 14
  • 15.
    PHASE REDUCE • Lesfichiers d’entrées sont partitionnés pour les reducers – Une clef est assignée à chaque reducer (pour travailler avec des fichiers provenant de différents mappers) – C’est pour cela que les combiners et la compression de fichiers sont importants : ils permettent de réduire le trafic réseau Etapes : • Shuffle : récupérer les fichiers produits par les mappers (en réalité c’est ce sens là) • Merge : fusionner les fichiers d’entrée déjà triés afin de produire l’ensemble de données d’entrée • Reduce : appliquer la fonction de réduction (ex : group by, somme, moyenne…) • Write : écrire les résultats finaux sur disque 15
  • 16.
    PHASE REDUCE :OPTIMISER LA LECTURE DES FICHIERS D’ENTRÉE • Les fichiers d’entrée sont récupérés depuis les emplacements locaux aux mappers  charge réseau à prévoir – Combiners – Compression – Partitionnement • Pour accélérer la récupération des fichiers pouvant être sur plusieurs mappers (donc machines) différents : multithreading 16
  • 17.
    PHASE REDUCE :OPTIMISER LE MERGE DES FICHIERS D’ENTRÉE • Les fichiers d’entrée sont récupérés et lus par le reducer • Chaque input est traitée – Soit en mémoire si le dataset tient – Soit sur disque si le dataset est supérieur • Les fichiers sont lus de telle manière à garder l’ordre afin d’appliquer la fonction de reduce de manière linéaire (Big-O(n)) • De la même manière que lors de l’étape de map, le reducer peut faire du spilling – Lorsque la mémoire est trop chargée, les données sont flushées sur disque et mergées entre elles • Pour éviter le spilling : io.sort.factor 17
  • 18.
    PHASE REDUCE :OPTIMISER L’ECRITURE DES FICHIERS FINAUX • Partition key (distribute by xxx in Hive) – pour les reducers • Car les data sont distribuées par clefs dans les reducers – si un reducer travaille sur plusieurs partitions • plusieurs RecordWriters  problème de performance • L’idée est donc de dédier les reducer à l’écriture sur une seule partition 18
  • 19.
    TUNING JVM • Réutiliserla JVM – Temps d’initialisation de la JVM à prendre en compte • Heap • JIT • … • Heap management – Dimensionner correctement la heap • Attention au GC 19
  • 20.
    OPTIMISATIONS HIVE/CASCADING • Mapjoins/Hashjoins: – S’assurer que l’ensemble utilisé pour la jointure tient effectivement en mémoire • UNION ALL/GROUP BY plutôt que d’utiliser des LEFT JOIN : moins de jobs générés – Hive peut lancer plusieurs jobs pour une requête • Sacrifier le temps d’exécution d’un job pour améliorer le temps de requêtage dans Hive 20
  • 21.
    RAPPEL 21 mapred.min.split.size mapred.max.split.size dfs.block.size (cluster wide) hive.merge.mapredfiles hive.merge.smallfiles.avgsize +compression + input format mapred.compress.map.output io.sort.mb io.sort.splill.percent io.sort.factor mapred.combiner.class mapred.reduce.parallel.copies mapred.reduce.child.java.optsmapred.map.child.java.opts
  • 22.
  • 23.
    CLUSTER MANAGEMENT YARN • Lapartie stockage ne bouge pas mais le JobTracker disparaît au profit d’une nouvelle architecture Composants : • Resource Manager • Application Manager • Scheduler • Embarqué dans Hadoop 2 – Possibilité de l’utiliser hors d’Hadoop mais quelques fonctions sont manquantes (ex : API de communication avec les executors) 23
  • 24.
    CLUSTER MANAGEMENT APACHE MESOS •« Resource offer » : CPU, RAM… • Le master Mesos propose une quantité de ressources à un framework à exécuter en fonction de : – Politiques d’organisation – Fair scheduling – Priorité • Il est aussi possible d’étendre via plugins (à développer) le système de mise à disponibilité de ressources • Côté développeur : définir les tasks et leurs ressources nécessaire pour le framework scheduler – API : JAVA/Scala, Python, C++… • Utilisable avec Hadoop mais aussi avec n’importe quel type de frameworks (ex : Spark) 24
  • 25.
    LE PLUS IMPORTANT: LE MONITORING/PROFILING • JobTracker – Possibilité de définir ses propres compteurs pour debug • Ganglia • Nagios/Centreon : monitoring bas niveau (CPU, RAM, I/O disque, I/O réseau…) • Starfish : optimisation de la configuration Hadoop (ex : mapred-site.xml) après analyse des logs de jobs 25
  • 26.
    PETITS CONSEILS • Sivos data tiennent en RAM… EVITEZ HADOOP !!!! • Si vos data peuvent tenir en RAM sur peu de machines… EVITEZ HADOOP – Spark – Gigaspaces (lol… go Spark) • En gros… tant que vous pouvez, évitez Hadoop  • Pour des requêtes qui ne prennent que peu de temps, évitez de lancer des jobs MR ou Hive ou autre… – Le temps d’initialisation des mappers et reducers est très long… • Et surtout : ME-SU-REZ !!!! – Il est très difficile d’anticiper les paramètres de configuration du cluster – Chaque job est différent si le dataset d’entrée n’est pas le même (ou si le job créé des data supplémentaires, cf. EXPLODE) 26
  • 27.
    QUESTIONS ? We cantalk about… #hadoop 27 #scalding #scala#sharks #summingbird #performance #mechanical-sympathy #hive #cascading #JVM