- 1.数据序列化
3.其它因素
1.数据序列化
spark提供两种序列化库
- java serialization: spark默认用java.io.Serialization类来序列化对象,可以通过继承java.io.Externalizable来控制性能
- Kryo serialzation: spark同时也可以用Kryo库来序列化对象。Kryo比java更快,更完善。推荐使用Kryo来序列化对象
2.内存调优
a.查看使用的内存: INFO BlockManagerMasterActor: Added rdd_0_1 in memory on mbk.local:50311 (size: 717.5 KB, free: 332.3 MB
b.使用适当的数据
- 结构趋向于使用对象数组,与原始类型数组
- 避免有许多小对象的嵌套的结构
- 考虑用数字值的ID而不是字符串的ID
- 如果内存小于32GB,可以设置JVM的属性符
-XX:+UseCompressedOops
使指针的大小为4字节而不是8字节,java7可以设置-XX:+UseCompressedStrings
,使存的ASCII的字符存储大小为8位
c.序列化RDD的储存
当对象仍然太大的时候,一个更简单的方法是通过以序列化格式的存储来减少对内存的占用。利用在RDD持久化API的序列化级别,例如MEMORY_ONLY_SER。Spark之后会存储对象成一个大的字节数组,这个方法的缺憾是读取RDD的时候会花更多的时候来deserialized.推荐使用Kryo,当你需要存储序列化的RDD的时候。
d.垃圾回收器调优
- 测量GC的影响,添加
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
到SPARK_JAVA_OPTS - 缓存的设置: 默认的情况下spark是利用66%配置好的Executor的内存来保存RDD。33%的内存在任务执行过程当中保存创建的对象,当出现任务执行缓慢与内存溢出的错误的时候,可以通过设置保存RDD内存的大小来减小内存的压力。在SparkConf中设置,
conf.set("spark.storage.memoryFraction", "0.5")
3.其它考虑因素
a.并行级别: 尽量使集群中每个节点都能运行到任务,推荐每个CPU的核心运行2-3个任务。Spark会根据文件的大小自动设置map任务的数量。
b.Reduce任务的内存使用:有时出现的outofmemory错误不是由于RDD不能在内存保存,而是因为reduce任务太大。spark的shuffle任务会建立 一个哈希表,通常会很大。简单的做法是提高并行的数量,令每个任务的数据量变小。spark高效地支持时间长度少到200ms的任务。
c.广播大的变量:通过广播可以大大地减小每个序列化的任务。