当前位置: 首页 > news >正文

【大数据学习 | Spark调优篇】Spark之内存调优

1. 内存的花费

1)每个Java对象,都有一个对象头,会占用16个字节,主要是包括了一些对象的元信息,比如指向它的类的指针。如果一个对象本身很小,比如就包括了一个int类型的field,那么它的对象头实际上比对象自己还要大。

JAVA对象 = 对象头 + 实例数据 + 对象填充(补余用的,用于保证对象所占空间是8个字节的整数倍)

2)Java的String对象,会比它内部的原始数据,要多出40个字节。因为它内部使用char数组来保存内部的字符序列的,并且还得保存诸如数组长度之类的信息。而且因为String使用的是UTF-16编码,所以每个字符会占用2个字节。比如,包含10个字符的String,会占用60个字节。

3)Java中的集合类型,比如HashMap和LinkedList,内部使用的是链表数据结构,所以对链表中的每一个数据,都使用了Entry对象来包装。Entry对象不仅有对象头,还有指向下一个Entry的指针,通常占用8个字节。

4)元素类型为原始数据类型(比如int)的集合,内部通常会使用原始数据类型的包装类型,比如用Integer来存储元素。

下面将从 Spark 中内存管理的概述开始,然后我们讨论可以采取的特定策略,以更有效地使用内存。特别是,我们将描述如何确定对象的内存使用情况,以及如何改进它——通过更改数据结构或以序列化格式存储数据。然后我们将介绍调整 Spark 的缓存大小和 Java 垃圾收集器。

2. 内存管理

Spark的内存可以大体归为两类:execution(运行内存)和storage(存储内存),前者包括shuffles、joins、sorts和aggregations所需内存,后者包括cache和节点间数据传输所需内存;

Spark1.6及以后,引入的统一内存管理机制,与静态内存管理的区别在于存储内存和执行内存共享同一块空间,可以动态占用对方的空闲区域,提供更好的性能。此种方式使得我们不需要修改内存比例。

3.  如何判断你的程序消耗了多少内存

这里有一个非常简单的办法来判断,你的spark程序消耗了多少内存。

1)首先,自己设置RDD的并行度,有下列方法:

a) 在parallelize()、textFile()等方法中,传入第二个参数,设置RDD的task 或 partition的数量;

b) 用SparkConf.set()方法,设置一个参数,spark.default.parallelism,可以统一设置这个application所有RDD的partition数量。

2)其次,在程序中将RDD cache到内存中,调用RDD.cache()方法即可。

3)最后,观察web ui

val cacheRdd = rdd.cache() //应该根据这个地方cache的结果,进行内存的调节

// count行动算子触发运算。

cacheRdd.count()

4. 优化数据结构

减少内存消耗的第一种方法是避免Java语法特性中所导致的额外内存的开销,比如基于指针的Java数据结构,以及包装类型。

有一个关键的问题,就是优化什么数据结构?其实主要就是优化你的算子函数,内部使用到的局部数据,或者是算子函数外部的数据。都可以进行数据结构的优化。优化之后,都会减少其对内存的消耗和占用。

优化方法:

1)能用数组取代,就不用集合。比如:用Array代替List。

2)能用字符串取代,就不用数组或集合。

3)能用int型取代,就不要用字符串;比如:Map的key可以用int取代字符串。

5. 对多次使用的RDD进行持久化或Checkpoint

RDD 持久化:

如果程序中,对某一个RDD,基于它进行了多次transformation或者action操作。那么就非常有必要对其进行持久化操作,以避免对一个RDD反复进行计算。

此外,如果RDD的持久化数据可能会丢失的(因为使用cache的时候),还要保证高性能,那么可以对RDD进行Checkpoint操作。

checkpoint:

checkpoint的意思就是建立检查点,类似于快照,当DAG计算过程出现问题了就可以从这个快照中恢复,当然我们也可以通过cache或者persist将中间的计算结果放到内存或者磁盘中,但也未必完全可靠,假如内存或者硬盘坏了,也会导致spark从头再根据rdd计算一遍,所以就有了checkpoint,其中checkpoint的作用就是将DAG中比较重要的中间数据做一个检查点将结果存储到一个高可用的地方比如HDFS。

使用方法:

6. 选择带有序列化的持久化级别

除了对多次使用的RDD进行持久化操作之外,还可以进一步优化其性能。如果RDD数据持久化到内存或磁盘时,如果内存不够就可能只缓存RDD的部分数据。

为了提高效率,可以采取序列化持久到内存,这样内存占用少。比如MEMORY_ONLY_SER、MEMORY_AND_DISK_SER等。

对于序列化的持久化级别,还可以使用Kryo序列化进一步优化,这样,可以获得更快的序列化速度,并且占用更小的内存空间。

http://www.lryc.cn/news/495507.html

相关文章:

  • Linux:文件系统inode
  • 力扣难题解析
  • 4.5-Channel 和 Flow:SharedFlow 和 StateFlow
  • Qt | TCP服务器实现QTcpServer,使用线程管理客户端套接字
  • 【提高篇】3.6 GPIO(六,寄存器介绍,下)
  • 【AI】数据,算力,算法和应用(3)
  • 深度学习笔记——生成对抗网络GAN
  • 网络安全开源组件
  • Python毕业设计选题:基于django+vue的智慧社区可视化平台的设计与实现+spider
  • Oracle LinuxR7安装Oracle 12.2 RAC集群实施(DNS解析)
  • M2芯片安装es的步骤
  • macos下brew安装redis
  • 第六届金盾信安杯-SSRF
  • 【论文投稿】国产游戏技术:迈向全球引领者的征途
  • 腾讯微众银行大数据面试题(包含数据分析/挖掘方向)面试题及参考答案
  • 【Linux】死锁、读写锁、自旋锁
  • Spring Web开发(请求)获取JOSN对象| 获取数据(Header)
  • 用c语言完成俄罗斯方块小游戏
  • SpringBoot整合Retry详细教程
  • JS API事件监听(绑定)
  • ceph手动部署
  • superset load_examples加载失败解决方法
  • wareshark分析mysql协议的数据包
  • HarmonyOS4+NEXT星河版入门与项目实战(25)------UIAbility启动模式(文档编辑案例)
  • webpack 项目访问静态资源
  • ‌UNION和UNION ALL区别
  • Rook入门:打造云原生Ceph存储的全面学习路径(下)
  • RabbitMQ消息可靠性保证机制6--可靠性分析
  • k8s容器存储接口 CSI 相关知识
  • jmeter基础_打开1个jmeter脚本(.jmx文件)