Fun[ctional] spark with scala

53
13 Junio 2016 Fun[ctional] Spark with Scala

Transcript of Fun[ctional] spark with scala

Page 1: Fun[ctional] spark with scala

13 Junio 2016

Fun[ctional] Sparkwith Scala

Page 2: Fun[ctional] spark with scala

Quienes somos

Fun[ctional] Spark with Scala

José Carlos García Serrano Arquitecto Big Data en Stratio.

Granadino e ingeniero por la ETSII, master de Big Data en la UTad, certificado en Spark y AWS

Amante de las nuevas tecnologías y de las arquitecturas basadas en Big Data

FanBoy de cosas como:

● Scala● Spark● Akka● MongoDB● Cassandra

Pero todos tenemos un pasado:

● Delphi● C++● BBDD SQL● Hadoop

Page 3: Fun[ctional] spark with scala

Quienes somos

Fun[ctional] Spark with Scala

David Vallejo Navarro Desarrollador Scala en Stratio.

Trabajando con Scala desde 2012 (si...cuando nadie sabía qué era eso de Scala)

Actualmente cursando un máster en Investigación informática.

He trabajado en:

● DSLs para la creación de aplicaciones sociales

● Sistemas distribuidos

● Aplicaciones WEB

● Migración de antiguas arquitecturas a Scala

● Y ahora, Big Data!

Ah! Y tengo un blog de Scala: www.scalera.es

Page 4: Fun[ctional] spark with scala

José Carlos García SerranoArquitecto Big Data

[email protected]

CONTACTO

ÍNDICE

INTRODUCCIÓN1

2

3

VENTAJAS DE SCALA EN SPARK

DESVENTAJAS DE SCALA EN SPARK4

David Vallejo NavarroDesarrollador Big Data

[email protected]

SCALA AVANZADO CON SPARK

Page 5: Fun[ctional] spark with scala

1 INTRODUCCIÓN

Page 6: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

¿Qué es Scala?

2003 - Martin Odersky, estando borracho, ve un anuncio de mantequilla de cacahuete Reese sobre

el chocolate y tiene una idea. Crea Scala, un lenguaje que unifica las construcciones de los

lenguajes funcionales y los orientados a objetos. Consigue cabrear a los partidarios de ambos tipos

de lenguaje que declaran al unísono la jihad.

Incomplete, and Mostly Wrong History of Programming Languages por James Iry

Page 7: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

¿Qué es Scala?

CARACTERÍSTICAS PRINCIPALES

CORRE EN LA JVM1

2

3

MULTIPARADIGMA

TIPADO ESTÁTICO

INFERENCIA DE TIPOS4

5 HERENCIA MÚLTIPLE

Page 8: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Scala en Noviembre de 2014

72.992 miembros319 meetups

Page 9: Fun[ctional] spark with scala

72.992 miembros319 meetups

Fun[ctional] Spark with Scala

Scala en Junio de 2016 (1 año y 7 meses después)

233.375 miembros570 meetups

Page 10: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Algunas empresas que usan Scala

Page 11: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Spark Scala

+ =

Page 12: Fun[ctional] spark with scala

2 VENTAJAS DESCALA ENSPARK

Page 13: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

2.1 Ventajas de usar Scala

• Uso de JVM

-> Librerías - Polimorfismo - Gestión

• Estáticamente tipado

-> Optimización del uso de memoria y de los algoritmos aplicados

• Modularidad

-> Grandes proyectos entendibles por humanos

• Sintaxis simple y rápido desarrollo

-> Programación funcional, poco código y simplicidad

• Multi-threading y concurrencia

-> Akka y la programación funcional son nuestros amigos

Page 14: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Los inicios como padawan scalero son duros y no puros ...

Page 15: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

Java??

Ventajas

• trait JavaNoMola {

val advantages : Seq[String] = ???

}

Desventajas

• No data-centric language

• Líneas de código infinitas

• Difícil uso de colecciones

• Var = efectos de lado

• Concurrencia descontrolada

Python??

Ventajas

• Data-centric language

• Fácil uso de colecciones

Desventajas

• Tipado dinámico

• Compilado mejor que interpretado

Performance - Errores

• No es modular

• Mala integración con Hadoop

• Api limitada de Streaming

Y por qué no en C ...

Page 16: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

Page 17: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

Probablemente en un futuro veremos a Spark como la colección de elementos distribuidos de Scala

Page 18: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

2.2 Ventajas de usar Scala en Spark

• Escrito en Scala

• RDD es una colección distribuida, funciones conocidas map, flatMap, groupBy, foreach, etc …

• Lambda va de serie

• RDD tipados -> Datasets tipados y no tipados

• Poco código para realizar ETLs y apps sencillas

• Datos inmutables

• Efectos de lado minimizados (Closure)

• Evaluación perezosa (Lazy)

Page 19: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

Funciones conocidas por cualquier escalero ...

def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U] = withScope { val cleanF = sc.clean(f) new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.flatMap(cleanF))}

private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag]( var prev: RDD[T], f: (TaskContext, Int, Iterator[T]) => Iterator[U], // (TaskContext, partition index, iterator) preservesPartitioning: Boolean = false) extends RDD[U](prev) {

override def compute(split: Partition, context: TaskContext): Iterator[U] = f(context, split.index, firstParent[T].iterator(split, context))

Page 20: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Page 21: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

val textFile = sc.textFile("hdfs://...")

val counts = textFile.flatMap(line => line.split(" "))

.map(word => (word, 1))

.reduceByKey(_ + _)

JavaRDD<String> textFile = sc.textFile("hdfs://...");

JavaRDD<String> words = textFile.flatMap(new FlatMapFunction<String, String>() {

public Iterable<String> call(String s) { return Arrays.asList(s.split(" ")); }

});

JavaPairRDD<String, Integer> pairs = words.mapToPair(new PairFunction<String, String, Integer>() {

public Tuple2<String, Integer> call(String s) { return new Tuple2<String, Integer>(s, 1); }

});

JavaPairRDD<String, Integer> counts = pairs.reduceByKey(new Function2<Integer, Integer, Integer>() {

public Integer call(Integer a, Integer b) { return a + b; }

});

Java

Típico word count, pero refleja la realidad … Scala vs Java vs Python

Scala Pythontext_file = sc.textFile("hdfs://...")

counts = text_file.flatMap(lambda line: line.split(" ")) \

.map(lambda word: (word, 1)) \

.reduceByKey(lambda a, b: a + b)

Page 22: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Page 23: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

Nuestra querida inmutabilidad ...

• Mutabilidad y concurrencia no mola -> Efectos de lado

• Al ser inmutable un RDD puede ser recreado en cualquier momento

• Difícil mantenimiento de datos que mutan -> update de memoria y disco -> Pésimo performance

• Queremos programación funcional y transformaciones que son funciones

Page 24: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

Lazy?? mismo concepto de una variable lazy de scala pero en RDD

• Todas las transformaciones se van añadiendo al DAG de operaciones

• Solo son ejecutadas cuando realizamos una acción

• Se computan las transformaciones de las que depende la acción

• Las que no dependan de la acción no son computadas

Odersky querría este concepto para sus colecciones ;)

Page 25: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

def collect(): Array[T] = withScope { val results = sc.runJob(this, (iter: Iterator[T]) => iter.toArray) Array.concat(results: _*)}

def map[U: ClassTag](f: T => U): RDD[U] = withScope { val cleanF = sc.clean(f) new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF))}

def runJob[T, U: ClassTag]( rdd: RDD[T], func: (TaskContext, Iterator[T]) => U, partitions: Seq[Int], resultHandler: (Int, U) => Unit): Unit = { if (stopped.get()) { throw new IllegalStateException("SparkContext has been shutdown") } val callSite = getCallSite val cleanedFunc = clean(func) logInfo("Starting job: " + callSite.shortForm) if (conf.getBoolean("spark.logLineage", false)) { logInfo("RDD's recursive dependencies:\n" + rdd.toDebugString) } dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, resultHandler, localProperties.get) progressBar.foreach(_.finishAll()) rdd.doCheckpoint()

Page 26: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

2.3 Optimizaciones en Scala

Tungsten

● Serialización

● DataSets

DataFrames

● UDFs más eficientes que en Python

MLlib

● Coste adicional de convertir Python objects a Scala objects

Recordemos el meetup de Fun[ctional] Spark with Scala ...

Page 27: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

Y antes de spark 1.6 ...

Page 28: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

2. VENTAJAS

desde Spark 1.4 tungsten ya optimizaba algunas funciones de DataFrames de Scala

Page 29: Fun[ctional] spark with scala

3 SCALA AVANZADOCON SPARK

Page 30: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3. Scala avanzado

Page 31: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.1 Implícitos

def mean(xs: RDD[Int]): Double = xs.sum / xs.count

mean(rdd)

Queremos calcular la media de un RDD:

Page 32: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.1 Implícitos

Implícitos: partes de código que se ejecutan sin ser llamados

Page 33: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.1 Implícitos

implicit val timeout = 5000

def tryConnection(dbUri: String)(implicit timeout: Int) = ???

tryConnection("127.0.0.1/8080")

case class Point(x: Int, y: Int)

implicit def tupleToPoint(tuple: (Int, Int)): Point = Point(tuple._1, tuple._2)

def sumPoints(p1: Point, p2: Point) = Point(p1.x + p2.x, p1.y + p2.y)

sumPoints(Point(1, 2), (3, 4))

Valores implícitos

Funciones implícitas

Page 34: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.1 Implícitos

implicit class RichSparkRDD(rdd: RDD[Int]) {

def mean: Double = rdd.sum / rdd.count}

rdd.mean //new RichSparkRDD(rdd).mean

Podemos utilizar una implicit class para expandir funcionalidad:

Page 35: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.2 Funciones de orden superior

Funciones que reciben funciones y/o devuelven funciones

Page 36: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.2 Funciones de orden superior

type Term = Inttype Result = Inttype Operation = (Term, Term) => Result

def add: Operation = (n1, n2) => n1 + n2def sub: Operation = (n1, n2) => n1 - n2

def calculate(n1: Term, n2: Term)(f: Operation): Result = f(n1, n2)

calculate(2, 5)(add)calculate(1, 6)((n1, n2) => n1 * n2)

Construyendo una calculadora

Page 37: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.2 Funciones de orden superior

def withSparkContext[T](name: String)(blockCode: SparkContext => T): T = {

val sparkConf = new SparkConf().setAppName(name).setMaster("local[4]") val sc = new SparkContext(sparkConf)

val result = blockCode(sc)

sc.stop()

result}

¿Y en Spark…?

withSparkContext("Meetup SDK") { sc =>

val myRDD = sc.parallelize(List(1, 2, 3, 4))

// ...}

Page 38: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.3 For comprehension

Map, flatMap, syntactic sugar ….

Page 39: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.3 For comprehension

Métodos map y flatMap

val myRDD = sc.parallelize(List(1, 2, 3, 4))

myRDD map (_ + 1) //RDD(2, 3, 4, 5)

myRDD flatMap (i => List(i - 1, i + 1)) // RDD(0, 2, 1, 3, 2, 4, 3, 5)

Page 40: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.3 For comprehension

Iterando sobre una colección de tweets

case class Tweet(id: Int, content: String, retweets: Int, user: String)

case class VipUserFactor(id: Int, factor: Double)

tweets.flatMap ( tweet => vipUsers.filter(_.id == tweet.id).map ( vipUser => tweet.retweets * vipUser.factor ))

Page 41: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.3 For comprehension

Syntactic sugar al rescate!

case class Tweet(id: Int, content: String, retweets: Int, user: String)

case class VipUserFactor(id: Int, factor: Double)

for { tweet <- tweets vipUser <- vipUsers if tweet.id == vipUser.id} yield tweet.retweets * vipUser.factor

Page 42: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.4 Type Classes

Patrón de diseño que nos permite extender funcionalidad a distintos tipos al vuelo usando implícitos

Page 43: Fun[ctional] spark with scala

trait MyCollection[T[Int]] {

def sum(coll: T[Int]): Double def size(coll: T[Int]): Long}

Fun[ctional] Spark with Scala

3.4 Type Classes

Quiero testear mi core con listas en memoria

implicit object RDDAsCollection extends MyCollection[RDD] { def sum(coll: RDD[Int]) = coll.sum def size(coll: RDD[Int]) = coll.count}

implicit object ListAsCollection extends MyCollection[List] { def sum(coll: List[Int]) = coll.sum def size(coll: List[Int]) = coll.size}

Page 44: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

3.4 Type Classes

Quiero testear mi core con listas en memoria

implicit class RichMyCollection[T[_]](coll: T[Int])(implicit ev: MyCollection[T]) {

def mean = ev.sum(coll) / ev.size(coll)

}

List(1, 2, 3).meanrdd.mean

Page 45: Fun[ctional] spark with scala

4 DESVENTAJASDE SCALAEN SPARK

Page 46: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Page 47: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

4. DESVENTAJAS

Desventajas de usar Scala en Spark

• Curva de aprendizaje para desarrolladores

• Curva de aprendizaje para Data Scientists en Machine Learning

• Costoso en tiempo para realizar PoC

• Código Javero

• Performance en la JVM (recordemos el anterior meetup)

• + Algoritmos implementados en Python - Algoritmos MLlib distribuidos

Page 48: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

4. DESVENTAJAS

override def hasNext: Boolean = { if (!finished) { if (!gotNext) { nextValue = getNext() if (finished) { closeIfNeeded() } gotNext = true } } !finished } override def next(): U = { if (!hasNext) { throw new NoSuchElementException("End of stream") } gotNext = false nextValue }}

private[spark] abstract class NextIterator[U] extends Iterator[U] { private var gotNext = false private var nextValue: U = _ private var closed = false protected var finished = false

def closeIfNeeded() { if (!closed) { closed = true close() } }

Código Spark = Java Style

Page 49: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

Haría vomitar al mismísimo Odersky ...

Page 50: Fun[ctional] spark with scala

Fun[ctional] Spark with Scala

4. DESVENTAJAS

JVM

• Los objetos de Java consumen más memoria de la que deberían

“abcd” 4 bytes en Nativo UTF-8 y 48 bytes en Java

• El GC de Java tiende a sobre trabajar y no tiene suficiente info.

Page 53: Fun[ctional] spark with scala

PREGUNTAS