Para comparar el rendimiento de Spark al usar Python y Scala, creé el mismo trabajo en ambos idiomas y comparé el tiempo de ejecución. Esperaba que ambos trabajos tomaran aproximadamente la misma cantidad de tiempo, pero el trabajo de Python solo tomó 27min
, mientras que el trabajo de Scala tomó 37min
(¡casi un 40% más!). También implementé el mismo trabajo en Java y también me tomó 37minutes
. ¿Cómo es posible que Python sea mucho más rápido?
Ejemplo mínimo verificable:
Trabajo de Python:
# Configuration
conf = pyspark.SparkConf()
conf.set("spark.hadoop.fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")
conf.set("spark.executor.instances", "4")
conf.set("spark.executor.cores", "8")
sc = pyspark.SparkContext(conf=conf)
# 960 Files from a public dataset in 2 batches
input_files = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312025.20/warc/CC-MAIN-20190817203056-20190817225056-00[0-5]*"
input_files2 = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312128.3/warc/CC-MAIN-20190817102624-20190817124624-00[0-3]*"
# Count occurances of a certain string
logData = sc.textFile(input_files)
logData2 = sc.textFile(input_files2)
a = logData.filter(lambda value: value.startswith('WARC-Type: response')).count()
b = logData2.filter(lambda value: value.startswith('WARC-Type: response')).count()
print(a, b)
Trabajo Scala:
// Configuration
config.set("spark.executor.instances", "4")
config.set("spark.executor.cores", "8")
val sc = new SparkContext(config)
sc.setLogLevel("WARN")
sc.hadoopConfiguration.set("fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")
// 960 Files from a public dataset in 2 batches
val input_files = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312025.20/warc/CC-MAIN-20190817203056-20190817225056-00[0-5]*"
val input_files2 = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312128.3/warc/CC-MAIN-20190817102624-20190817124624-00[0-3]*"
// Count occurances of a certain string
val logData1 = sc.textFile(input_files)
val logData2 = sc.textFile(input_files2)
val num1 = logData1.filter(line => line.startsWith("WARC-Type: response")).count()
val num2 = logData2.filter(line => line.startsWith("WARC-Type: response")).count()
println(s"Lines with a: $num1, Lines with b: $num2")
Simplemente mirando el código, parecen ser idénticos. Miré a los DAG y no me dieron ninguna idea (o al menos me falta el conocimiento para llegar a una explicación basada en ellos).
Realmente agradecería cualquier puntero.
python
scala
apache-spark
pyspark
maestromusica
fuente
fuente
Respuestas:
Su suposición básica, que Scala o Java deberían ser más rápidos para esta tarea específica, es simplemente incorrecta. Puede verificarlo fácilmente con aplicaciones locales mínimas. Scala uno:
Python uno
Resultados (300 repeticiones cada uno, Python 3.7.6, Scala 2.11.12),
Posts.xml
desde el volcado de datos hermeneutics.stackexchange.com con una combinación de patrones coincidentes y no coincidentes:Como puede ver, Python no solo es sistemáticamente más rápido, sino que también es más consistente (menor difusión).
El mensaje para llevar es: no creas FUD sin fundamento : los idiomas pueden ser más rápidos o más lentos en tareas específicas o con entornos específicos (por ejemplo, aquí Scala puede verse afectado por el inicio de JVM y / o GC y / o JIT), pero si reclamas como "XYZ es X4 más rápido" o "XYZ es lento en comparación con ZYX (..) Aproximadamente, 10 veces más lento" generalmente significa que alguien escribió un código realmente malo para probar cosas.
Editar :
Para abordar algunas inquietudes planteadas en los comentarios:
local_connect_and_auth
, y no es más que un archivo asociado a un socket ). Una vez más, tan barato como se pone cuando se trata de comunicación entre procesos.Edición 2 :
Como jasper-m estaba preocupado por el costo de inicio aquí, uno puede demostrar fácilmente que Python todavía tiene una ventaja significativa sobre Scala, incluso si el tamaño de entrada aumenta significativamente.
Aquí están los resultados para 2003360 líneas / 5.6G (la misma entrada, solo duplicada varias veces, 30 repeticiones), que excede todo lo que puede esperar en una sola tarea de Spark.
Tenga en cuenta los intervalos de confianza no superpuestos.
Edición 3 :
Para abordar otro comentario de Jasper-M:
Eso es simplemente incorrecto en este caso particular:
DataFrame
) implementa gran cantidad de funcionalidades de forma nativa en Python, con entrada de excepción, salida y comunicación entre nodos.fuente
El trabajo de Scala lleva más tiempo porque tiene una configuración incorrecta y, por lo tanto, los trabajos de Python y Scala han recibido recursos desiguales.
Hay dos errores en el código:
sc.hadoopConfiguration
es un lugar incorrecto para configurar cualquier configuración de Spark. Debe establecerse en laconfig
instancia a la que pasanew SparkContext(config)
.[AGREGADO] Teniendo en cuenta lo anterior, propondría cambiar el código del trabajo de Scala a
y vuelva a probarlo de nuevo. Apuesto a que la versión de Scala será X veces más rápida ahora.
fuente