在之前的博客文章中,我们回顾并调查了过去一年中对Apache Spark所做的性能改进。在这篇文章中,我们期待并与您分享下一章,我们称之为Project Tungsten。2014年见证了Spark在大规模排序方面创造了世界纪录,并看到了从Python到SQL到机器学习的整个引擎的重大改进。然而,性能优化是一个永无止境的过程。

自项目启动以来,Project Tungsten将是Spark执行引擎的最大变化。它集中于显着提高的效率存储器和CPU用于火花应用,推性能更接近现代硬件的限制。这项工作包括三项举措:

  1. 内存管理和二进制处理:利用应用程序语义显式管理内存,消除JVM对象模型和垃圾回收的开销
  2. 缓存感知计算:利用内存层次结构的算法和数据结构
  3. 代码生成:使用代码生成来利用现代编译器和CPU

对CPU效率的关注是由于Spark工作负载越来越受CPU和内存使用而不是IO和网络通信的影响。最近对大数据工作负载性能的研究表明了这一趋势(Ousterhout等人),我们在Databricks Cloud客户的持续调整和优化工作中得出了类似的发现。

为什么CPU成为新的瓶颈?这件事情是由很多原因导致的。一个是硬件配置提供越来越大的聚合IO带宽,例如网络中的10Gbps链路和用于存储的高带宽SSD或条带HDD阵列。从软件的角度来看,Spark的优化器现在允许许多工作负载通过修剪给定作业中不需要的输入数据来避免重要的磁盘IO。在Spark的shuffle子系统中,序列化和散列(受CPU限制)已被证明是关键瓶颈,而不是底层硬件的原始网络吞吐量。所有这些趋势意味着今天的Spark通常受到CPU效率和内存压力的限制,而不是IO。

1.内存管理和二进制处理

JVM上的应用程序通常依赖JVM的垃圾收集器来管理内存。JVM是一项令人印象深刻的工程技术,旨在作为许多工作负载的通用运行时。但是,随着Spark应用程序突破性能的边界,JVM对象和GC的开销变得不可忽视。

Java对象具有很大的固有内存开销。考虑一个简单的字符串“abcd”,它将使用UTF-8编码存储4个字节。但是,JVM的本机String实现以不同方式存储它以促进更常见的工作负载。它使用带有UTF-16编码的2个字节对​​每个字符进行编码,每个String对象还包含一个12字节的头和8字节的哈希码,如Java对象布局工具的以下输出所示。

java.lang.String对象内部:
OFFSET SIZE TYPE DESCRIPTION VALUE0 4(对象标题)...4 4(对象标题)......8 4(对象标题)......12 4 char [] String.value []16 4 int String.hash 020 4 int String.hash32 0
实例大小:24个字节(由Instrumentation API报告)

在JVM对象模型中,一个简单的4字节字符串总共超过48个字节!

JVM对象模型的另一个问题是垃圾收集的开销。在较高的层次上,分代垃圾收集将对象分为两类:具有高分配/解除分配率(年轻代)的对象(旧代)。垃圾收集器利用年轻代对象的瞬态特性来有效地管理它们。当GC能够可靠地估计物体的生命周期时,这种方法很有效,但如果估计值关闭(即一些瞬态物体溢出到老一代),则无法实现。由于这种方法最终基于启发式和估计,因此提高性能可能需要GC调整的“黑魔法”,有许多参数可以为JVM提供有关对象生命周期的更多信息。

然而,Spark不仅仅是一个通用的应用程序。Spark了解数据如何通过各个计算阶段以及作业和任务的范围。因此,Spark知道比JVM垃圾收集器更多关于内存块生命周期的信息,因此应该能够比JVM更有效地管理内存。

为了解决对象开销和GC低效问题,我们引入了一个显式内存管理器来转换大多数Spark操作,以直接针对二进制数据而不是Java对象进行操作。这构建于sun.misc.UnsafeJVM提供的高级功能之上,该功能公开了C风格的内存访问(例如显式分配,释放,指针算术)。此外,Unsafe方法是固有的,这意味着每个方法调用都由JIT编译为单个机器指令。

在某些领域,Spark已经开始使用显式托管内存。去年,Databricks贡献了一个新的基于Netty的网络传输,它使用类似内存管理器的jemalloc显式管理所有网络缓冲区。这对扩大Spark的shuffle操作并赢得Sort Benchmark至关重要。

其中的第一部分将出现在Spark 1.4中,其中包含一个哈希表,该表直接对二进制数据进行操作,内存由Spark明确管理。与标准Java相比HashMap,这种新实现更少的间接开销,并且对垃圾收集器是不可见的。

这仍在进行中,但最初的绩效结果令人鼓舞。如上所示,我们使用不同的哈希映射比较聚合操作的吞吐量:一个使用我们的新哈希映射的堆模式,一个使用offheap,一个使用java.util.HashMap。新的哈希表在单个线程中每秒支持超过100万次聚合操作,大约是java.util.HashMap吞吐量的2倍。更重要的是,在不调整任何参数的情况下,随着内存利用率的增加,它几乎没有性能下降,而JVM默认最终因GC而崩溃。

在Spark 1.4中,此哈希映射将用于DataFrames和SQL的聚合,在1.5中,我们将为大多数其他操作(如排序和连接)准备好数据结构。在许多情况下,这将消除调整GC以实现高性能的需要。

2.缓存感知计算

在我们解释缓存感知计算之前,让我们重新审视“内存中”计算。Spark被广泛称为内存计算引擎。这个术语的真正含义是Spark可以有效地利用集群上的内存资源,以比基于磁盘的解决方案高得多的速率处理数据。但是,Spark还可以处理大于可用内存的数据顺序,透明地溢出到磁盘并执行外部操作,如排序和散列。

类似地,缓存感知计算通过更有效地使用L1 / L2 / L3 CPU缓存来提高数据处理的速度,因为它们比主存储器快几个数量级。在分析Spark用户应用程序时,我们发现大部分CPU时间都花在等待从主内存中提取数据上。作为Project Tungsten的一部分,我们正在设计缓存友好的算法和数据结构,因此Spark应用程序将花费更少的时间等待从内存中获取数据,并将更多时间用于执行有用的工作。

考虑将记录排序作为示例。标准排序过程将存储指向记录的指针数组,并使用quicksort交换指针,直到所有记录都被排序。由于顺序扫描访问模式,排序通常具有良好的高速缓存命中率。但是,对指针列表进行排序的缓存命中率较低,因为每个比较操作都需要解除引用指向内存中随机位置记录的两个指针。

那么我们如何改进排序的缓存局部性呢?一种非常简单的方法是将每个记录的排序键与指针并排存储。例如,如果排序键是64位整数,那么我们使用128位(64位指针和64位键)将每个记录存储在指针数组中。这样,每个快速排序比较操作仅以线性方式查找指针 - 密钥对,并且不需要随机存储器查找。希望上面的插图让您了解我们如何重新设计基本操作以实现更高的缓存局部性。

这如何适用于Spark?大多数分布式数据处理可以归结为一小部分操作,例如聚合,排序和连接。通过提高这些操作的效率,我们可以提高整个Spark应用程序的效率。我们已经构建了一个可识别缓存的排序版本,比以前的版本快3倍。这种新排序将用于基于排序的shuffle,高基数聚合和排序合并连接运算符。到今年年底,大多数Spark的最低级别算法将升级为高速缓存感知,从而提高从机器学习到SQL的所有应用程序的效率。

3.代码生成

大约一年前,Spark 在SQL和DataFrames中引入了用于表达式评估的代码生成。表达式评估是计算age > 35 && age < 40特定记录上的表达式(例如“ ”)的值的过程。在运行时,Spark动态生成用于评估这些表达式的字节码,而不是为每一行逐步执行较慢的解释器。与解释相比,代码生成减少了原始数据类型的装箱,更重要的是,避免了昂贵的多态函数调度。

在之前的博客文章中,我们证明代码生成可以将许多TPC-DS查询加速几乎一个数量级。我们现在正在将代码生成覆盖范围扩展到大多数内置表达式。此外,我们计划将代码生成水平从一次记录表达式评估提高到矢量化表达式评估,利用JIT的功能在现代CPU中利用更好的指令流水线,这样我们就可以一次处理多个记录。

我们还在表达式评估之外的领域应用代码生成,以优化内部组件的CPU效率。我们对应用代码生成非常兴奋的一个领域是加速数据从内存二进制格式到有线协议的转换。如前所述,shuffle通常是数据序列化而不是底层网络的瓶颈。通过代码生成,我们可以提高序列化的吞吐量,从而提高shuffle网络吞吐量。

上面的图表比较了使用Kryo序列化程序和代码生成的自定义序列化程序在一个线程中混洗800万个复杂行的性能。代码生成的序列化程序利用了单个shuffle中的所有行具有相同的模式并为其生成专用代码的事实。这使得生成的版本比Kryo版本快2倍。

钨和超越

Project Tungsten是一项广泛的计划,将在接下来的几个版本中影响Spark核心引擎的设计。第一部分将登陆Spark 1.4,其中包括用于Spark的DataFrame API中的聚合操作的显式托管内存以及自定义序列化程序。扩展的二进制内存管理和缓存感知数据结构将在Spark 1.5中出现。项目Tungsten的几个部分利用DataFrame模型。我们还将尽可能地改进Spark的RDD API 的改进。

钨还有一些长期可能性。特别是,我们计划研究编译到LLVM或OpenCL,因此Spark应用程序可以利用现代CPU中的SSE / SIMD指令和GPU中的宽并行性来加速机器学习和图形计算中的操作。

Spark的目标始终是提供一个单一平台,用户可以在其中获得最佳的分布式算法,用于任何数据处理任务。性能是该目标的关键部分,而Project Tungsten旨在让Spark应用程序以裸机提供的速度运行。请继续关注Databricks博客,了解有关Project Tungsten组件的长期文章。我们还将在即将于6月在旧金山举行的Spark峰会上报告有关该项目的详细信息。

  • 注:手绘图由我们在Confluent(Martin Kleppmann)的朋友们启发

原文链接:https://databricks.com/blog/2015/04/28/project-tungsten-bringing-spark-closer-to-bare-metal.html

Project Tungsten:将Apache Spark更接近裸机相关推荐

  1. Project Tungsten:让Spark将硬件性能压榨到极限

     Project Tungsten:让Spark将硬件性能压榨到极限 摘要:对于Spark来说,通用只是其目标之一,更好的性能同样是其赖以生存的立足之本.北京时间4月28日晚,Databricks ...

  2. 什么是Apache Spark?这篇文章带你从零基础学起

    导读:Apache Spark是一个强大的开源处理引擎,最初由Matei Zaharia开发,是他在加州大学伯克利分校的博士论文的一部分.Spark的第一个版本于2012年发布. Apache Spa ...

  3. Apache Spark 内存管理详解

    原文出处: IBM developerWorks Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 ...

  4. Apache Flink vs Apache Spark——感觉二者是互相抄袭啊 看谁的好就抄过来 Flink支持在runtime中的有环数据流,这样表示机器学习算法更有效而且更有效率...

    Apache Flink是什么 Flink是一款新的大数据处理引擎,目标是统一不同来源的数据处理.这个目标看起来和Spark和类似.没错,Flink也在尝试解决 Spark在解决的问题.这两套系统都在 ...

  5. 新版本来袭:Apache Spark 1.5新特性介绍

    Apache Spark社区2015年9月9日发布了1.5版本,该版本由230+开发人员和80+机构参与,修复了1400多个补丁,该版本可以通过 http://spark.apache.org/dow ...

  6. Apache Spark3.0什么样?一文读懂Apache Spark最新技术发展与展望

    简介: 阿里巴巴高级技术专家李呈祥带来了<Apache Spark 最新技术发展和3.0+ 展望>的全面解析,为大家介绍了Spark在整体IT基础设施上云背景下的新挑战和最新技术进展,同时 ...

  7. Apache Spark处理大数据入门,看这一篇就够了

    作者 Srini Penchikala ,译者 丛一 什么是Spark Apache Spark是一个围绕速度.易用性和复杂分析构建的大数据处理框架.最初在2009年由加州大学伯克利分校的AMPLab ...

  8. 调整Apache Spark应用程序的Java垃圾收集

    调整Apache Spark应用程序的Java垃圾收集 王道远黄洁 由王道远和黄杰 发表于公司博客 2015年5月28日 这是来自英特尔SSG STO大数据技术小组的朋友的客座文章. 来源地址: ht ...

  9. 全方位掌握Apache Spark 2.0七步走(二)

    2019独角兽企业重金招聘Python工程师标准>>> 在上一篇普及过Spark的相关概念之后,让我们继续深入研究它的核心结构以及好用的API,本篇视频内容丰富,机(fan)智(qi ...

  10. 大规模数据处理Apache Spark开发

    大规模数据处理Apache Spark开发 Spark是用于大规模数据处理的统一分析引擎.它提供了Scala.Java.Python和R的高级api,以及一个支持用于数据分析的通用计算图的优化引擎.它 ...

最新文章

  1. centos ipsec tunnel 配置
  2. USB、TTL电平、232电平之间的相互转换
  3. 《双人成行》如何炼就“教科书级别的合作体验游戏”典范?
  4. 修饰性形容词-big、good、high_35
  5. mysql+主从同步+用户,MySQL主从同步
  6. x86_64 Linux 运行时栈的字节对齐
  7. 再谈 MySQL 备份
  8. -bash: mysql: command not found
  9. Atitit 知识搜索 信息检索的方法总结 目录 1. 目录搜索 1 1.1. 向下同级搜索 1 1.2. 向上目录抽象搜索 1 2. hash搜索模式 1 2.1. 关键词搜索 主题搜索 1 2
  10. 计算机系统的确认与验证,确认与验证(指南).pdf
  11. windows强制删除文件命令
  12. 3分钟教会你用excel做多层饼图
  13. Effective C++ 学习笔记 第二章:构造、析构、赋值运算
  14. Linux应用编程之时间编程
  15. 社区团购小程序有哪些赚钱方式
  16. android banner指示器高度,Android 广告轮播 -ConvenientBanner 指示器大小、bottomMargin,leftMarfin的修改。...
  17. 伪概念催生人工智能行业泡沫 2018年或迎大洗牌
  18. graphpad图片怎么导出矢量图_Graphpad Prism 8如何绘制生存曲线
  19. 查看SQL Server的实例名
  20. 谷歌剧变:李飞飞李佳离职后,现在轮到云CEO出局

热门文章

  1. 一维搜索算法——黄金分割法原理与实现
  2. cad图层置顶的lisp_cad中如何将一个图层置于上层
  3. w10计算机名重新启动此计算机后,win10电脑关机后自动重启怎么回事?原因与解决办法...
  4. “此电话号码无法用于进行验证” 注册gmail邮箱手机号码不能验证的解决方法(已解决)
  5. 码云仓库第一次上传代码流程和git相关操作合集(持续更新)
  6. 金山词霸笔试题目笔记
  7. 英文论文写作小贴士(2)
  8. wincc逻辑运算符_wincc中表达式及公式
  9. 计算机教学问卷调查,信息技术在数学课堂教学中的应用:数学课堂信息技术应用调查问卷...
  10. FASTDB中文手册