前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Open Source Talk 02|首个中国团队自己培养的OpenJDK Reviewer背后的那些事

Open Source Talk 02|首个中国团队自己培养的OpenJDK Reviewer背后的那些事

作者头像
腾讯开源
发布2021-07-07 18:40:10
5850
发布2021-07-07 18:40:10
举报

About「Open Source Talk」栏目

开源无边界,分享有价值。Code is not cold,「Open Source Talk」栏目,将陆续邀请众多开源嘉宾做客,和大家一起分享和交流开源道路中的成长心得。以知识和分享为起点,传承开源的星星火光。

本期引言

本篇文章,傅杰博士将回顾自己十年来的OpenJDK开源经历,讲述自己一路上遇到的坎坷、成长和心得。

1

开源:协同共建,互利共赢

        十年前,我从西安交通大学保送至中科院计算所硕博连读,加入计算所龙芯CPU团队,主力承担龙芯上高性能Java虚拟机C2编译器的研发,从此与OpenJDK结缘。加入腾讯后,主要从事Kona JDK在大数据和机器学习等领域的探索和实践。

        2018 年腾讯930 变革后,成立了开源协同项目组和对外开源管理办公室,正式将开源提升到公司战略层面。我所在的Tencent Kona JDK Oteam(含多位OpenJDK社区Reviewer/Committer/Author)正是基于开源协同的模式组建和运营的。开源是一种互利共赢的生态建设。将代码贡献到OpenJDK开源社区,不仅使得全球用户共享研发成果,也让贡献者获得成就感。此外,通过开源互动,还可以不断提升团队的认知水平和研发能力,逐步扩大团队影响力。团队leader经常告诫我们不要做开源的食利者,要积极贡献开源,做社区的良好公民。正是在这种开源文化和理念的指引下,Kona积极参与OpenJDK社区,贡献有价值的代码,获得了开源社区的点赞和致谢。

2

腾讯Kona开源贡献概览  

  腾讯Kona是JDK15/16官宣的全球Notable贡献者,并连续两次蝉联国内贡献度第一。截止到今年5月,Kona向OpenJDK社区最重要的JDK主干项目累计贡献了150多个Patch,涉及HotSpot虚拟机内核(Compiler、GC和Runtime)、SVC、Core Libraries和Infrastructure等领域。其中,比较突出的包括:Vector API、C2编译器、ZGC、jmap大堆Heap Dump加速等。下面以Kona在OpenJDK社区系统性参与开源贡献的首个Java前沿新特性,Vector API为例,介绍Kona的开源输出。

Vector API本质上是一组通用Java向量加速的编程接口,对典型数据科学场景具有显著的加速效果。例如,根据官方公布的数据,Vector API对矩阵乘法的加速为2~5倍;对于点积运算的加速高达14~16倍。Kona在生产实践中首次适配并完善了Vector API对AVX512高性能向量指令集的支持,解决了多个由编译器Bug导致的正确性问题,修复了由于memory barrier缺失导致的稳定性问题。上述开源贡献解决了Vector API长期遗留的正确性和稳定性痛点,使得Vector API在广告训练等实际业务系统中落地,为产业界的规模化应用蹚平了道路。值得注意的是,Kona对Vector API架构改进和性能优化也有贡献。

在架构设计方面,Kona修复了Vector API对C2编译器强耦合的顶层设计缺陷。如上图所示,虚拟机执行引擎包括解释器、C1编译器和C2编译器三种。修复前,Vector API无法脱离C2编译器执行,与C2在事实上构成强耦合关系。但是,Vector API作为Java语言层面的API,不应依赖于特定执行引擎的实现,理论上应该被所有执行引擎支持。发现上述缺陷后,我们从顶层Java编程接口出发,自顶向下分析了Vector API的架构设计和执行流程,一直深入到虚拟机执行引擎的实现细节,成功定位到强耦合的原因是向量长度选择逻辑仅在C2中有实现。于是,我们为另外两款执行引擎(Interpreter和C1)补充实现了向量长度选择模块,并且与社区专家进行了多个回合的研讨,最终修复了该缺陷。此后,Vector API和其它Java API一样,可以跑在任意一种执行引擎上。

在性能优化方面,Kona是JDK17中SVML(Short Vector Math Library)向量加速新特性三大贡献者之一(另外两位是Intel和Oracle)。SVML是一款高性能向量优化数学库,用于进一步加速Vector API的向量数学运算。受C2编译器历史遗留的至少两个double才能向量化的限制,官方最初的SVML无法对单个double数据进行加速。但实际业务中会经常使用单个double的数学运算,优化的需求也很大。经过反复分析和实验,我们打破了C2编译器强制要求至少两个double的不合理限制,巧妙地将单个double数据转换为64位向量进行SVML加速。优化后性能成倍提升,部分2~4倍,个别高达8~9倍,如上图所示。

3

OpenJDK社区经历与感受

      今年5月,我有幸获得了由社区专家发起的OpenJDK Reviewer的提名(如下图所示),并于两周之后高票通过。在此特别感谢团队的培养和帮助,同时也感谢OpenJDK社区对Kona的认可。

       虽然我十年前就开始接触OpenJDK,但真正参与社区却是从2018年12月才开始的。2019年11月,在贡献了30多个Patch后,我有幸被社区专家提名为OpenJDK Committer。之后又经历了约19个月收获颇丰的社区历练,我累计贡献了140多个Patch,成功晋级OpenJDK Reviewer。十年回首,自己经历了很多坎坷,也走过了不少弯路。在此分享一些个人的经验和教训,希望对大家能有所帮助。

       首先,社区参与要趁早。作为一名开发者,自己最后悔的事情就是没有及早参与开源社区。加入社区之前,视野狭小闭塞,能力和经验积累主要靠从实践中自我摸索,成长缓慢。加入社区后,每天接触到的都是领域前沿,与社区顶级专家的交流讨论也成为常态,进步显著加快。对于刚加入开源社区的新手而言,最重要的事情是学习社区规则。下图展示了OpenJDK社区重要的规则:

       OpenJDK社区将开发者从初级到高级划分为Contributor、Author、Committer和Reviewer四种角色。其中,只要签署了OCA(Oracle Contributor Agreement)协议并贡献了1个Patch之后,就自动成为OpenJDK的Contributor。当贡献的Patch数目达到2个以后,就可以向社区申请成为Author。

       成为Author后,开发者便拥有了JDK的JBS账号,以后贡献会更加方便。但Author还没有代码的Push权限。当贡献了至少8个重要的Patch后,经社区提名并投票通过后,可以晋升为Committer。注意,不是任意8个Patch,而是8个硬核(英文表述为“Significant”)贡献才有资格被提名Committer。

       除了最基本的数量要求之外,社区对Committer和Reviewer的提名更关注Patch本身的价值、难度和质量,这也是为何大多数OpenJDK开发者长期停留在Author级别难以晋升的原因。晋升为Committer后,就获得了向OpenJDK代码库Push代码的权限。

       Reviewer的提名则要求至少有32个硬核的贡献,难度比Committer进一步加大。在代码评审方面,OpenJDK明确要求虚拟机内核HotSpot的代码至少两人Review通过之后才能入库,并且在入库前强制等待24小时,以保证全球各个时区的开发者都有机会对代码修改进行评审。

       其次,不惧权威,大胆质疑。我在做前面提及的SVML优化时,过程并非一帆风顺。当我的优化代码编写完毕后,却发现POW算子的性能反而下降了约27%。起初,我怀疑是自己的实现有问题。我花了一天时间,对该场景涉及的调用链路和汇编代码进行了分析和排查,但并没有发现问题。第二天,确认自己的优化代码实现没有问题后,我及时将方向转换到了SVML库本身。可能有人觉得,SVML库是由业界权威Intel提供的,不可能有问题。但实际上,后来的排查结果证实就是SVML本身的Bug导致的性能下降。我在多种机器上全面评估了SVML中POW算子的性能,发现在非AVX512机型上性能下降,唯有AVX512机型性能才提升。于是,我纠正了官方SVML的优化逻辑,当且仅当底层硬件支持AVX512指令时才对POW算子启用优化,从而规避了SVML的性能下降问题。上述优化策略的改进在OpenJDK社区很快得到了Intel专家的认可,并且迅速合并到了OpenJDK社区。如果盲目相信权威,我所遇到的性能下降问题可能永远无解。

       再次,注意理论与工程的差异。从理论上分析理所应当的事情,在实际工程实践中未必如此。在此,跟大家分享自己优化Math.pow(x, 0.5)的真实故事。从数学角度分析,将Math.pow(x, 0.5)替换成Math.sqrt(x)是等价的。但是,在编译器的工程实现中,上述直接替换却是错误的。这是因为根据IEEE754的规范,当x的值为-0.0和负无穷大时,计算机计算得到的结果并不相等!IEEE754浮点运算规范规定如下:

代码语言:javascript
复制
Math.pow(-0.0, 0.5) = 0.0
Math.sqrt(-0.0) = -0.0
代码语言:javascript
复制
Math.pow(Double.NEGATIVE_INFINITY, 0.5) = Infinity
Math.sqrt(Double.NEGATIVE_INFINITY) = NaN

注意:在编译器实现时,0.0和-0.0也是两个不同的浮点结果。因此,在编译器优化实践中,绝对不允许将Math.pow(x, 0.5)直接替换为Math.sqrt(x)。随后,我实现了一种已被JDK17接受的优化方案:仅对x > 0时才进行替换。故大家在工程实践中务必注意与理论的差异。

       最后,尊重知识产权。尊重他人的知识产权,切勿将别人的开源代码,不加任何引用说明地据为己有。OpenJDK社区对代码知识产权的尊重令人惊讶。例如,我曾经修复了一个由处理器弱一致性访存模型触发的GC稳定性问题(Bug ID:JDK-8229169),该Bug影响包括x86在内的所有处理器,尤其影响ARM等弱一致性访存处理器。我最初只在JDK14上进行了修复。后来由于其重要性,在我不知情的前提下,该Patch被社区GC专家反向移植到了JDK8和JDK11等业界广泛使用的版本。但是,令我惊讶的是,在JDK8等所有被反向移植的源代码库中,对应代码的作者竟然保留了我的名字,如下图中红色方框所示。在整个移植过程中,我没有出一份力,却依然保留我为代码的作者,连commit信息都一模一样。当时我就震惊了,从此也更加懂得了尊重他人的知识产权。

4

晋升OpenJDK Committer/Reviewer的秘诀

      如何才能获得开源社区认可,并成长为Committer、Reviewer呢?

      持续贡献有价值的代码是关键。凡是实际业务场景需要的改进都是有价值的。自己对OpenJDK的贡献绝大部分来源于广告训练、大数据和腾讯云等实际业务系统。在此,我谨向相关业务开发和运维同学表示衷心感谢。从实际业务需求出发,持续贡献有价值的代码,是快速获得开源社区认可的唯一秘诀。

       兴趣和坚守缺一不可。OpenJDK是复杂度极高的底层基础软件,学习门槛高,开发调试难度大。因此,初学者在Bug修复和性能优化时往往面临巨大的困难和挑战。如果没有强烈的兴趣爱好作为支撑,就容易被困难险阻吓跑,也就无法通过长期历练成为社区的Committer/Reviewer。曾有同行问我是否因为KPI才做开源。我回答不是。Kona从来都没有把社区贡献设为KPI,兴趣爱好是我们最大的驱动力。 我们心中的“执念”是通过腾讯JDK前沿实践的贡献,解决Java在生产中的长期短板和痛点,让Java长久成功。此外,开发者需要认准一个方向长期坚守下去,由浅入深,逐步构建自己的品牌与核心竞争力。从这个角度讲,开发者需要有坐几年冷板凳的心理准备。

       以兴趣爱好为驱动,持续贡献有价值的代码,长期坚守并深耕一个方向,那么开发者成长为Committer/Reviewer就指日可待了!

       最后,欢迎大家加入到Tencent KonaJDK开源项目中来,和傅杰导师一起探索开源的广阔世界!

       ➡️开源项目介绍|Tencent KonaJDK

https://github.com/Tencent 

(点击文末阅读原文直接访问)

请给项目 一个 Star ! 欢迎提出你的 issue 和 PR!

 国内镜像地址:

https://git.code.tencent.com/Tencent_Open_Source

(登录后才能访问公开项目)

腾讯工蜂源码系统为开源开发者提供完整、最新的腾讯开源项目国内镜像

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯开源 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯 Kona
腾讯 Kona 是一个基于 OpenJDK 定制的,生产环境可用,高性能,安全稳定,兼容多种运行平台的 OpenJDK 开源发行版本。提供企业级 JDK 服务,由腾讯专业技术团队提供技术维护、性能优化及安全保障等服务,为您提供最优的 Java 云生产环境及解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档