[英]Why is Spark performing worse when using Kryo serialization?
我为我的 Spark 作业启用了 Kryo 序列化,启用了需要注册的设置,并确保我的所有类型都已注册。
val conf = new SparkConf()
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
conf.set("spark.kryo.registrationRequired", "true")
conf.registerKryoClasses(classes)
conf.registerAvroSchemas(avroSchemas: _*)
作业的挂钟时间性能下降了约 20%,混洗的字节数增加了近 400%。
鉴于Spark 文档建议 Kryo 应该更好,这对我来说似乎真的很令人惊讶。
Kryo 明显比 Java 序列化更快、更紧凑(通常高达 10 倍)
我以我的数据示例手动调用了 Spark 的org.apache.spark.serializer.KryoSerializer
和org.apache.spark.serializer.JavaSerializer
实例上的serialize
方法。 结果与 Spark 文档中的建议一致:Kryo 产生了 98 个字节; Java 产生了 993 个字节。 这确实是 10 倍的改进。
一个可能的混淆因素是被序列化和混洗的对象实现了 Avro GenericRecord
接口。 我尝试在SparkConf
注册 Avro 模式,但没有显示出任何改进。
我尝试创建新类来混洗数据,这些数据是简单的 Scala case class
,不包括任何 Avro 机器。 它没有提高 shuffle 性能或交换的字节数。
Spark 代码最终归结为以下内容:
case class A(
f1: Long,
f2: Option[Long],
f3: Int,
f4: Int,
f5: Option[String],
f6: Option[Int],
f7: Option[String],
f8: Option[Int],
f9: Option[Int],
f10: Option[Int],
f11: Option[Int],
f12: String,
f13: Option[Double],
f14: Option[Int],
f15: Option[Double],
f16: Option[Double],
f17: List[String],
f18: String) extends org.apache.avro.specific.SpecificRecordBase {
def get(f: Int) : AnyRef = ???
def put(f: Int, value: Any) : Unit = ???
def getSchema(): org.apache.avro.Schema = A.SCHEMA$
}
object A extends AnyRef with Serializable {
val SCHEMA$: org.apache.avro.Schema = ???
}
case class B(
f1: Long
f2: Long
f3: String
f4: String) extends org.apache.avro.specific.SpecificRecordBase {
def get(field$ : Int) : AnyRef = ???
def getSchema() : org.apache.avro.Schema = B.SCHEMA$
def put(field$ : Int, value : Any) : Unit = ???
}
object B extends AnyRef with Serializable {
val SCHEMA$ : org.apache.avro.Schema = ???
}
def join(as: RDD[A], bs: RDD[B]): (Iterable[A], Iterable[B]) = {
val joined = as.map(a => a.f1 -> a) cogroup bs.map(b => b.f1 -> b)
joined.map { case (_, asAndBs) => asAndBs }
}
您是否知道可能会发生什么,或者我如何获得 Kryo 应该提供的更好的性能?
如果您的单个记录大小太小,并且有大量记录可能会使您的工作变慢。尝试增加缓冲区大小,看看是否有任何改进。
如果还没有完成,请尝试下面的一个..
val conf = new SparkConf()
.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
// Now it's 24 Mb of buffer by default instead of 0.064 Mb
.set("spark.kryoserializer.buffer.mb","24")
参考: https : //ogirardot.wordpress.com/2015/01/09/changed-sparks-default-java-serialization-to-kryo/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.