Dart编译技术在服务端的探索和应用

前言

最近闲鱼技术团队在Flutter+Dart的多端一体化的基础上,实现了FaaS研发模式。Dart吸取了其它高级语言设计的精华,例如Smalltalk的Image技术、JVM的HotSpot和Dart编译技术又师出同门。由Dart实现的语言容器,它可以在启动速度、运行性能有不错的表现。Dart提供了AoT、JIT的编译方式,JIT拥有Kernel和AppJIT的运行模式,此外服务端应用有各自不同的运行特点,那么如何选择合理的编译方法来提升应用的性能?接下来我们用一些有典型特点的案例来引入我们在Dart编译方案的实践和思考。

案例详情

相应的,我们准备了短周期应用(EmptyMain & Fibonnacci & faas_tool),长周期应用(HttpServer分别来说明不同的编译方法在各种场景下的性能表现

测试环境参考

#实验机1
Mac OS X 10.14.3 
Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz * 4 / 16GB RAM#实验机2
Linux x86_64
Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz * 4 / 8GB RAM#Dart版本
Dart Ver. 2.2.1-edge.eeb8fc8ccdcef46e835993a22b3b48c0a2ccc6f1 #Java HotSpot版本
Java build 1.8.0_121-b13 
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)#GCC版本
Apple LLVM version 10.0.1 (clang-1001.0.46.3)
Target: x86_64-apple-darwin18.2.0
Thread model: posix

短周期应用

Case1. EmptyMain

例子是一个空函数实现,以此来评估语言平台本身的启动性能,我们使用默认参数编译一个snapshot

#1.默认条件下的app-jit snapshot生成
dart snapshot-kind=app-jit snapshot=empty_main.snapshot empty_main.dart

测试结果

 

  • 作为现代高级语言Dart和Java在启动速度上在同一水平线
  • C语言的启动速度是其它语言的20x,基本原因是C没有Java、Dart语言平台的Runtime
  • Kernel和AppJIT方式运行有稳定的微小差异,总体AppJIT优于Kernel

Case2. Fibonacci数列

我们分别用C、Java、Dart用递归实现Fibonacci(50)数列,来考察编译工作对性能的影响。

long fibo(long n){if(n < 2){return n;}return fibo(n - 1) + fibo(n - 2);
}

AppJIT使用优化阈值实现激进优化,这样编译器在Training Run中立即获得生成Optimized代码

#2.执行激进优化          
dart --no-background-compilation \--optimization-counter-threshold=1 \ --snapshot-kind=app-jit \--snapshot=fibonacci.snapshotfibonacci.dart

将Fibonacci编译成Kernel

#3.生成Kernel snapshot
dart --snapshot=fibonacci.snapshot fibonacci.dart

AoT的Runtime不在Dart SDK里,需要自行编译AoT Runtime

#4.AoT编译
pkg/vm/tools/precompiler2 fibonacci.dart fibonacci.aot#5.AoT的方式执行
out/ReleaseX64/dart_precompiled_runtime fibonacci.aot

测试结果

 

  • Dart JIT对比下,AppJIT在激进优化后性能稍好于Kernel,差距微小,编译的成本占比可以忽略不计
  • Dart AoT模式下的性能约为JIT的1/6不到
  • JIT运行模式下,HotSpot的执行性能最优,优于Dart AppJIT 25%以上
  • 包括C语言在内的AoT运行模式性能均低于JIT,Dart AppJIT性能优于25%

问题

AoT由于自身的特性(和语言无关),无法在运行时基于Profile实现代码优化,峰值性能在此场景下要差很多,但是为何Dart VM比HotSpot有25%的差距?接下来我们针对Fibonacci做进一步优化

#6.编译器调优,调整递归内联深度
dart --inlining_recursion_depth_threshold=5 fibonacci.snapshot 50#7.编译器调优,HotSpot调整递归内联深度
java -XX:MaxRecursiveInlineLevel=5 Fabbonacci 50

测试结果

  • HotSpot VM性能全面领先于Dart VM;两者在最优情况下HotSpot VM的性能优于Dart 9%左右
  • Dart VM 借助JIT调优,性能有大幅提升,相比默认情况有40%左右的提升
  • Dart AppJIT 性能微弱领先Kernel

也许也不难想象JVM HotSpot目前在服务器开发领域上的相对Dart成熟,相比HotSpot,DartVM的“出厂设置”比较保守,当然我们也可以大胆猜测,在服务端应用下应该还有除JIT的其它优化空间;
和Case1相同,Kernel模式的性能依然低于AppJIT,主要原因是Kernel在运行前期需要把AST转换为堆数据结构、经历Compile、Compile Optimize等过程,而在适当Training run后的AppJIT snapshot在VM启动时以优化后的IL(中间代码)执行,但很快Kernel会追上App-jit,最后性能保持持平。有兴趣的读者可以参阅Vyacheslav Egorov Dart VM的文章。

Case3. FaaS容器编译工具

在前面我们提到过Dart版本的FaaS语言容器,为追求极致的研发体验,我们需要缩短用户Function打包到部署运行的时间。就语言容器层面而言,Dart提供的Snapshot技术可以大大提升启动速度,但是从用户Function到Snapshot(如下图)生成所产生的编译时间在不做优化的情况下超过10秒,还远远达不到极致体验的要求。我们这里通过一些测试,来寻找提升性能的途径

faas_tool是一个完全用Dart编写的代码编译、生成工具。依托于faas_tool, Function的编写者不用关心如何打包、接入中间件,faas_tool提供一系列的模版及代码生成工具可以将用户的使用成本降低,此外faas_tool还提供了HotReload机制可以快速响应变更。

这次我们提供了基于AoT、Kernel、AppJIT的用例来执行Function构建流程,分别记录时间消耗、中间产物大小、产物生成时间。为了验证在JIT场景下DartVM是否可通过调整Complier的行为带来性能提升,我们增加了JIT的测试分组

测试结果

FaaS编译工具-执行情况柱形图 

  • AoT>AppJIT>kernel,其中AoT比优化后的AppJIT有3倍左右性能提升,性能是Source的1000倍
  • JIT(Kernel, AppJIT)分组下,通过在运行时减少CompilerOptimize或暂停PGO可以提升性能

很显然faas_tool最终选择了AoT编译,但是性能结果和Case2大相径庭,为了搞清楚原因我们进一步做一下CPU Profile

CPU Profile

AppJIT

Dart App-jit模式 43%以上的时间参与编译,当然取消代码优化,可以让编译时间大幅下降,在优化情况下可以将这个比率下降到13%

Kernel


Kernel模式有61%以上的CPU时间参与编译工作, 如果关闭JIT优化代码生成,性能有15%左右提升,反之进行激进优化将有1倍左右的性能损耗

AoT下的编译成本

AoT模式下在运行时几乎编译和优化成本(CompileOptimized、CompileUnoptimized、CompileUnoptimized 占比为0),直接以目标平台的代码执行,因此性能要好很多。

P.S. DartVM 的Profile模块在后期的版本升级更改了Tag命名, 有需要进一步了解的读者参考VM Tags

附:DartVM调优和命令代码

#8.模拟单核并执行激进优化           
dart --no-background-compilation \--optimization-counter-threshold=1 \ tmp/faas_tool.snapshot.kernel #9.JIT下关闭优化代码生成
dart --optimization-counter-threshold=-1 \ tmp/faas_tool.snapshot.kernel #10. Appjit verbose snapshot
dart --print_snapshot_sizes \--print_snapshot_sizes_verbose \--deterministic  \--snapshot-kind=app-jit \--snapshot=/tmp/faas_tool.snapshot faas_tool.dart \#11.Profile CPU 和 timeline 
dart --profiler=true \--startup_timeline=true \--timeline_dir=/tmp \--enable-vm-service \--pause-isolates-on-exit faas_tool.snapshot

长周期应用

HttpServer

我们用一个简单的Dart版的HttpServer作为典型长周期应用的测试用例,该用例中有JsonToObject、ObjectToJson的转换,然后response输出。我们分别用Source、Kernel以及AppJIT的方式在一定的并发量下运行一段时间

void processReq(HttpRequest request){try{final List<Map<String,dynamic>> buf = <Map<String,dynamic>>[];final Boss boss = new Boss(numOfEmployee: 10);//Json反序列化对象getHeadCount(max: 20).forEach((hc){boss.hire(hc.idType, hc.docId);buf.add(hc.toJson());});request.response.headers.add('cal','${boss.calc()}');//Json对象转JsonStringrequest.response.write(jsonEncode(buf));request.response.close().then((v) => counter_success ++).timeout(new Duration(seconds:3)).catchError((e) => counter_fail ++));}  catch(e){request.response.statusCode = 500;counter_fail ++;request.response.close();}
}

测试结果


 
Y轴表示成功的请求量,X轴为时间

  • 上面三种无论是何种方式启动,最终的运行时性能趋向一致,编译成本在后期可以忽略不计,这也是JIT的运行特点
  • 在AppJIT模式下在应用启动起初就有接近峰值的性能,即使在Kernel模式下也需要时间预热达到峰值性能,Source模式下VM启动需要2秒以上,因此需要相对更长时间达到峰值性能。从另一方面看应用很快完成了预热,不久达到了峰值性能

P.S. 长周期的应用Optimize Compiler会经过Optimize->Deoptimize->Reoptimize的过程, 由于此案例比较简
单,没体现Deoptimize到Reoptimize的表现

附:VM调优脚本

#12.调整当前isolate的新生代大小,默认2M最大32M的新生代大小造成频繁的YGC
dart --new_gen_semi_max_size=512  \--new_gen_semi_initial_size=512  \ http_server.dart \--interval=2 

总结和展望

Dart编译方式的选择

  • 编译成本为主导的应用,应优先考虑AoT来提高应用性能
  • 长周期的应用在启动后期编译成本可忽略,应该选择JIT方式并开启Optimize Compiler,让优化器介入
  • 长周期的应用可以选择Kernel的方式来提升启动速度,通过AppJIT的方式进一步缩短warmup时间

AppJIT减少了编译预热的成本,这个特性非常适合对一些高并发应用在线扩容。Kernel作为Dart编译技术的前端,其平台无关性将继续作为整个Dart编译工具链的基础。

在FaaS构建方案的选择

通过CPU Profile得出faas_tool是一个编译成本主导的应用,最终选择了AoT编译方案,结果大大提升了语言容器的构建的构建速度,很好满足了faas对开发效率的诉求

仍需改进的地方

从JIT性能表现来看,DartVM JIT的运行时性和HotSpot相比有提升余地,由于Dart语言作为服务端开发的历史不长,也许随着Dart在服务端的技术应用全面推广,相信DarVM在编译器后端技术上对服务器级的处理器架构做更多优化

 

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519259.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python + ElasticSearch:有了这个超级武器,你也可以报名参加诗词大会了! | 博文精选...

来源 | CSDN 博客作者 | 天元浪子责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;意犹未尽的诗词大会正月十六&#xff0c;中国诗词大会第五季落下帷幕。从2016年2月12日第一季于开播&#xff0c;迄今恰好四周年。在这个舞台上&#xff0c;时年…

Node.js 应用故障排查手册 —— 大纲与常规问题指标简介

楔子 你是否想要尝试进行 Node.js 应用开发但是又总听人说它不安全、稳定性差&#xff0c;想在公司推广扩张大前端的能力范畴和影响又说服不了技术领导。 JavaScript 发展到今天&#xff0c;早已脱离原本浏览器的战场&#xff0c;借助于 Node.js 的诞生将其触角伸到了服务端、P…

蚂蚁金服CTO程立:做工程要有“拧螺丝”的精神

“一台机器可能有无数颗螺丝&#xff0c;需要一个一个地拧&#xff0c;而且需要一圈一圈地拧&#xff0c;才能让系统间严丝合缝&#xff0c;顺利工作。代码的世界里&#xff0c;一个项目到底成功与否&#xff0c;也是取决于几个模型的关键特殊设置&#xff0c;就像拧螺丝一样。…

linux 环境安装DBI和DBD_03

文章目录一、软件下载二、安装DBI2.1. DBI下载2.2. 解压2.3. 安装依赖2.4. 编译2.5. 执行测试2.6. 安装2.6. 修改权限三、安装DBD-ORACLE组件3.1. DBI下载3.2. 修改权限3.3. 切换用户3.4. 解压3.5. 进入目录3.6. 初始化环境变量3.6. 查看配置的环境变量是否配置3.7. 刷新配置文…

像数据科学家一样思考:12步指南(上)

介绍 目前&#xff0c;数据科学家正在受到很多关注&#xff0c;因此&#xff0c;有关数据科学的书籍正在激增。我看过很多关于数据科学的书籍&#xff0c;在我看来他们中的大多数更关注工具和技术&#xff0c;而不是数据科学中细微问题的解决。直到我遇到Brian Godsey的“像数…

Mybatis-plus 大数据量数据流式查询通用接口

文章目录一、案例需求二、使用案例&#xff1a;2.1. 自定义查询接口2.2. 逻辑处理类2.3. 调用案例2.4. 具体逻辑处理案例三、企业案例3.1. key名称获取3.2. 逻辑类测试3.3.最后一个批次处理方案四、 通用SQL预编译处理4.1. 业务场景4.2. xml形式4.3. 注解形式五、企业案例5.1. …

基于MaxCompute的数仓数据质量管理

声明 本文中介绍的非功能性规范均为建议性规范&#xff0c;产品功能无强制&#xff0c;仅供指导。 参考文献 《大数据之路——阿里巴巴大数据实践》——阿里巴巴数据技术及产品部 著。 背景及目的 数据对一个企业来说已经是一项重要的资产&#xff0c;既然是资产&#xff…

IP应用加速 – DCDN迈入全栈新篇章

4月11日&#xff0c;第七届"亚太内容分发大会"暨CDN峰会国际论坛中&#xff0c;阿里云资深技术专家姚伟斌发布了DCDN子产品IP应用加速&#xff08;IPA&#xff09;。IPA是基于阿里云CDN本身的资源优化&#xff0c;对传输层&#xff08;TCP&UDP&#xff09;协议进…

十年磨一剑,王坚自研的MaxCompute如何解决世界级算力难题

大数据时代&#xff0c;随着企业数据规模的急剧增长&#xff0c;传统软件已无法承载&#xff0c;这也推动了大数据技术的发展&#xff0c;Google、AWS、微软等硅谷巨头纷纷投入大数据技术的研发&#xff1b;而在国内&#xff0c;王坚也在十年前带领阿里云团队研发MaxCompute&am…

matlab和robotstudio,MATLAB与Robotstudio建立socket通信(初探)

前记:听一首《不想病》&#xff0c;歌词唱开头&#xff1a;做什么都不对&#xff0c;说什么都浪费&#xff0c;想什么我都可悲....&#xff1b;感觉就是不一样&#xff0c;好歌&#xff01;哎&#xff0c;&#xff0c;&#xff0c;回到正题。好多事要去做&#xff0c;还得挤时间…

贾扬清:我对人工智能方向的一点浅见

阿里妹导读&#xff1a;作为 AI 大神&#xff0c;贾扬清让人印象深刻的可能是他写的AI框架Caffe &#xff0c;那已经是六年前的事了。经过多年的沉淀&#xff0c;成为“阿里新人”的他&#xff0c;对人工智能又有何看法&#xff1f;最近&#xff0c;贾扬清在阿里内部分享了他的…

Node.js 应用故障排查手册 —— 类死循环导致进程阻塞

类死循环导致进程阻塞 楔子 在实践篇一中我们看到了两个表象都是和 CPU 相关的生产问题&#xff0c;它们基本也是我们在线上可能遇到的这一类问题的典型案例&#xff0c;而实际上这两个案例也存在一个共同点&#xff1a;我们可以通过 Node.js 性能平台 导出进程对应的 CPU Pro…

如何使用5个Python库管理大数据?

来源 | medium编译 | 武明利责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;如今&#xff0c;Python真是无处不在。尽管许多看门人争辩说&#xff0c;如果他们不使用比Python更难的语言编写代码&#xff0c;那么一个人是否真是软件开发人员&…

如何把创建ECS(CreateInstance)作为触发器来触发函数计算

问题描述 函数计算虽然不支持直接集成到ECS的管控事件上&#xff0c;但是函数计算本身是支持日志服务作为触发器的。即可以配置日志服务中logstore里的增强日志作为触发器来触发函数计算服务中的函数&#xff0c;同时可以传递project 和 logstore的name以及beginCursor/endCur…

ORACLE添加字段、删除字段

文章目录1. 删除表2. 创建表3. 添加字段4. 删除指定字段5. 修改指定字段长度1. 删除表 DROP TABLE SYS_JOB;2. 创建表 -- CREATE TABLE CREATE TABLE SYS_JOB (JOB_ID NUMBER(30) NOT NULL,JOB_NAME VARCHAR2(30) NOT NULL ); ALTER TABLE SYS_JOB ADD CONSTRA…

像数据科学家一样思考:12步指南(中)

像数据科学家一样思考&#xff1a;12步指南&#xff08;上&#xff09;《像数据科学家一样思考》 7-工程产品 下一步是建立统计软件。如果统计是分析和从数据中得出结论的框架&#xff0c;那么软件就是将这个框架付诸行动的工具。数据科学家必须为任何项目做出许多软件选择。如…

2020云计算,是四强争霸还是赢家通吃?

来源 | 架构师技术联盟责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;近日&#xff0c;谷歌母公司Alphabet首次公布了谷歌云计算业务的数据&#xff0c;这一举动将云计算行业重新推到了聚光灯下。众所周知&#xff0c;全球云市场竞争激烈&…

加载程序中数据库账号密码加密策略wallet_04

文章目录1. 切换到oracle用户2. 创建wallet目录3. 创建wallet 账户4. 查看创建的wallet5. 创建wallet目录6. 查看证书7. 把证书拷贝到客户端8. 在客户端的sqlnet.ora里添加9. 客户端的tnsnames.ora10. 测试登陆11. oracle环境变量oracle服务端创建wallet 1. 切换到oracle用户 …

利用丁香园数据生成疫情分布地图(R语言)| 博文精选

来源 | CSDN 博客作者 | 万里写入胸怀间责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;疫情牵动大家&#xff0c;除了做好分内工作&#xff0c;管好自己不给社会添乱&#xff0c;也就是只能持续关注疫情了。现在各大门户平台都上线了疫情实时地…

php连接数据库性能测试,无需安装配置,多操作系统支持数据库及性能测试

iBoxDB是一个NoSQL数据库, 有SQLite的特性,但拥有更强大的Replication功能,支持更多的数据类型,自动完成ORMSQLite是全球知名度Top 10的数据库之一, 在文章 中对 SQLite 与 MySQL进行了一个事务中1万次插入测试, 测试的结果是"sqlite3用时仅0.4s,mysql用时2.2s"iBoxD…