SparkCore(4)调优

概述:Spark的调优主要有三个方面

 

1.Data Serialization  ****

(1)Java serialization:默认情况下,Spark使用Java的ObjectOutputStream框架序列化对象,并且可以使用您创建的任何实现Java .io. serializable类。还可以通过扩展java.io.Externalizable更紧密地控制序列化的性能。Java序列化是灵活的,但通常相当缓慢,并导致许多类的大型序列化格式。

package SparkReview.Core4

import org.apache.spark.storage.StorageLevel
import org.apache.spark.{SparkConf, SparkContext}

import scala.collection.mutable.ArrayBuffer
import scala.util.Random

object SerializaitonApp {
  def main(args: Array[String]): Unit = {
    val sparkConf=new SparkConf().setMaster("local[2]").setAppName("Serialization")
    val sc=new SparkContext(sparkConf)


    val names=Array[String]("G301","G302","G303")
    val ganders=Array[String]("male","famale")
    val address=Array[String]("beijing","shenzhen","hangzhou","yongkang")

    val infos=new ArrayBuffer[InFo]()//对象用来表示通用的、固定长度的原始二进制数据缓冲区。
    // ArrayBuffer 不能直接操作,而是要通过类型数组对象或 DataView 对象来操作,
    // 它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

    for (i<-1 to 100000){
      val name=names(Random.nextInt(3))
      val gender=ganders(Random.nextInt(2))
      val addres=  address(Random.nextInt(4))
      infos+=InFo(name,gender,addres)
    }
    val rdd=sc.parallelize(infos)
   // rdd.persist(StorageLevel.MEMORY_ONLY)  //这个是34M
    rdd.persist(StorageLevel.MEMORY_ONLY_SER)   //这个是28仅仅只是小了一点,体现了java序列化的弊端
    rdd.count()
    sc.stop()
  }
  case class InFo(name: String,gender:String,address:String)


}

(2)Kryo serialization:Spark还可以使用Kryo库(版本2)更快地序列化对象。与Java序列化相比,Kryo要快得多,紧凑得多(通常高达10x,这个有点夸张),但它不支持所有可序列化的类型,并且要求您预先注册在程序中使用的类,以获得最佳性能。

1)通过 spark-defaults.conf 添加 spark.serializer                 org.apache.spark.serializer.KryoSerializer

2)因为没有注册,所以它要去存储你的所有类名和对象信息,所以Memory变大了

2.Memory Tuning

在调优内存使用时有三个考虑因素:

对象使用的内存数量(您可能希望整个数据集适合于内存)、

访问这些对象的成本以及

垃圾收集的开销(如果对象的周转率很高)。

默认情况下,Java对象的访问速度很快,但与字段中的原始数据相比,很容易消耗2-5倍的空间。这是由几个原因造成的:每个不同的Java对象都有一个对象标头,大约16个字节,包含指向其类的指针之类的信息。对于一个只有很少数据的对象(比如一个Int字段),这可能比数据大。Java字符串对原始字符串数据的开销约为40字节(因为它们将其存储在一个字符数组中,并保留额外的数据,比如长度),并且由于字符串内部使用UTF-16编码,将每个字符存储为两个字节。

因此,一个10个字符的字符串可以很容易地消耗60个字节。常用的集合类,如HashMap和LinkedList,使用链接数据结构,其中每个条目都有一个包装器对象(例如Map.Entry)。这个对象不仅有一个头,而且还有指向列表中下一个对象的指针(通常每个字节8个字节)。基元类型的集合通常将它们存储为框形对象,比如java.lang.Integer。本节将首先概述Spark中的内存管理,然后讨论用户在应用程序中更有效地使用内存的具体策略。特别地,我们将描述如何确定对象的内存使用情况,以及如何通过更改数据结构或以序列化格式存储数据来改进它。然后,我们将讨论Spark缓存大小的调优和Java垃圾收集器。

3.Memory Management Overview

4.Determining Memory Consumption

(1)作用:要确定数据集所需的内存消耗的大小,最好的方法是创建RDD,将其放入缓存中,并查看web UI中的“存储”页面。页面将告诉您RDD占用了多少内存。

(2)要估计特定对象的内存消耗,可以使用SizeEstimator的估计方法,这对于试验不同的数据布局来削减内存使用,以及确定广播变量在每个执行程序堆上占用的空间大小非常有用。

package SparkReview.Core4

import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.util.SizeEstimator.estimate
object DeterminingMemory {
  def main(args: Array[String]): Unit = {
    val sparkConf=new SparkConf().setMaster("local[2]").setAppName("DeterMiningMemory")
    val sc=new SparkContext(sparkConf)
    val a=sc.textFile("E:\\若泽数据\\零基础大数据篇第三期\\Hadoop综合编程\\infos.txt")
//TODO...查看数据的大小
println(estimate(a)) //(1)estimate查看数据的大小,这对于确定广播变量将占用多少堆空间非常有用
    /**缓存对象时每个执行程序或每个对象将占用的空间
      *反序列化形式。这与序列化对象的大小不同,序列化对象的大小将不同
    *通常要小得多。*/
//(2)缓存通过webUI的storage来看
    sc.stop()

  }

}

5.Level of Parallelism(并行度)

除非为每个操作设置足够高的并行度,否则集群不会得到充分利用。Spark会根据文件的大小自动设置要在每个文件上运行的map任务的数量(不过您可以通过SparkContext的可选参数来控制它)。对于分布式的reduce操作,如groupByKey和reduceByKey,它使用最大的父RDD分区数量。您可以将并行级别作为第二个参数传递(参见spark)。或设置config属性spark.default.parallelism以更改默认值。通常,我们建议集群中的每个CPU核心执行2-3个任务(防止task闲置)。

6.Memory Usage of Reduce Tasks

简述:就是就多给点exectuor跑的快一点

7.Data Locality  ****

这就是对应RDD的五大特性之一的,最优位置去计算

Data locality is how close data is to the code processing it. There are several levels of locality based on the data’s current location. In order from closest to farthest:

  • PROCESS_LOCAL data is in the same JVM as the running code. This is the best locality possible
  • NODE_LOCAL data is on the same node. Examples might be in HDFS on the same node, or in another executor on the same node. This is a little slower than PROCESS_LOCAL because the data has to travel between processes
  • NO_PREF data is accessed equally quickly from anywhere and has no locality preference
  • RACK_LOCAL data is on the same rack of servers. Data is on a different server on the same rack so needs to be sent over the network, typically through a single switch
  • ANY data is elsewhere on the network and not in the same rack
    • 这是比较长了,默认3s时间长了,1s好点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值