Spark性能优化----(概述)

一、内存消耗在什么地方
     1、每个Java对象,都有一个对象头,会占用16个字节,主要是包括了一些对象的元信息,比如指向它的类的指针。如果一个对象本身很小,比如就包括了一个int类型的field,那么它的对象头实际上比对象自己还要大。
     2、Java的String对象,会比它内部的原始数据,要多出40个字节。因为它内部使用char数组来保存内部的字符序列的,并且还得保存诸如数组长度之类的信息。而且因为String使用的是UTF-16编码,所以每个字符会占用2个字节。比如,包含10个字符的String,会占用60个字节。
     3、Java中的集合类型,比如HashMap和LinkedList,内部使用的是链表数据结构,所以对链表中的每一个数据,都使用了Entry对象来包装。Entry对象不光有对象头,还有指向下一个Entry的指针,通常占用8个字节。
     4、元素类型为原始数据类型(比如int)的集合,内部通常会使用原始数据类型的包装类型,比如Integer,来存储元素。
二、如何判断程序消耗了多少内存
     1、首先,自己设置RDD的并行度,有两种方式:要不然,在parallelize()、textFile()等方法中,传入第二个参数,设置RDD的task / partition的数量;要不然,用SparkConf.set()方法,设置一个参数,spark.default.parallelism,可以统一设置这个application所有RDD的partition数量。
     2、其次,在程序中将RDD cache到内存中,调用RDD.cache()方法即可。
     3、最后,观察Driver的log,你会发现类似于:“INFO BlockManagerMasterActor: Added rdd_0_1 in memory on mbk.local:50311 (size: 717.5 KB, free: 332.3 MB)”的日志信息。这就显示了每个partition占用了多少内存。
     4、将这个内存信息乘以partition数量,即可得出RDD的内存占用量。
三.在Spark内存管理调优中,我们需要重点关注的有两类内存:
    1.ExecutionMemory
        ExecutionMemory用于spark计算中的shuffles、 joins、sorts 、 aggregations这些操作
    2.storageMemory
        storageMemory用于缓存数据和保存广播变量数据 。下面参数均已spark2.2为准,不同版本会有些差异
四、分配公式
    1)spark内存管理源码入口:
        SparkEnv.scala,代码片段如下
        val useLegacyMemoryManager = conf.getBoolean("spark.memory.useLegacyMode", false)
        val memoryManager: MemoryManager =
        if (useLegacyMemoryManager) {
            new StaticMemoryManager(conf, numUsableCores)
        } else {UnifiedMemoryManager(conf, numUsableCores)}
        通过源码可知,现在的spark内存管理有两种:
              1.静态内存管理StaticMemoryManager
              2.统一内存管理UnifiedMemoryManager,
        通过参数spark.memory.useLegacyMode控制
    2)静态内存管理内存计算公式(源码见StaticMemoryManager.scala):
         ExecutionMemory = systemMemory *spark.shuffle.memoryFraction*spark.shuffle.safetyFraction=executor-memory*0.2*0.8
         storageMemory = systemMemory*spark.storage.memoryFraction*spark.storage.safetyFraction=executor-memory*0.6*0.9
    3)统一内存管理内存计算公式(源码见UnifiedMemoryManager.scala):
         预留内存reservedMemory=300M
         假设spark 应用分配的executor内存为systemMemory=2G可(通过参数--executor-memory 2g设置),systemMemory实际值要比设置executor-memory的稍小
         (ExecutionMemory + storageMemory) = (systemMemory-reservedMemory)* spark.memory.fraction =(2048-300)*0.6=1048.8M (实际会比该值稍小)
         storageMemory= (systemMemory-reservedMemory) * spark.memory.fraction * spark.memory.storageFraction=(2048-300)*0.6*0.5=524.4M
 

猜你喜欢

转载自blog.csdn.net/qq_36381640/article/details/82960841