C++ 程序员是应该承认 C++ 不如 Rust,还是应该承认 C++ 不如 GC 语言?
c++现状非常危险,在外网上被全面围攻
反正搞c++的可谓是八仙过海,各显神通
这里吐槽一下国内的c++程序员,麻烦多睁开眼睛看世界,看看现在鬼佬都有什么技术成果,国内c++那些忽悠人的还在说上个世纪的那些经验,就像我跟豹哥说的那样
你嘴里不断重复这些老(旧)经验,不能证明你的技术有多好,恰恰相反,只能证明你足够老
you can't teach an old dog new tricks
就像有些c++程序员,来我评论区蹭流量的时候,我说ffm,结果它说java 17,当时就晕了,ffm是22的成果,你看17当然啥都看不出来,你咋不说1.7呢?
现在是2024年,你不要活在1994年,然后张口大谈你穿越到现代化社会的经验好吧?
先说gc吧,用实际例子来说明,国外是怎样优化gc,让java达到取代c++的地步
先给出一个典型案例,那就是graal项目,这个就是典型的,用java来替换c++的案例,源代码在这里:
https://github.com/oracle/graalgraal本质上是一个jit编译器,更确切一点说,是编译器的后端
因为openjdk的前端,javac,已经全部用java实现了,现在只有后端也就是jvm里面的jit编译器,也就是c1&c2,尤其是c2,c1是客户端编译器后端,主要用c2,c2是c++实现的
graal跟c2一样,实现了编译器后端(jit),确切滴说是graal jit,graal jit完全由java实现,c2完全由c++实现,graal jit vs c2,你可以在外网上搜索到很多对比的文章,简单说结论就是,graal jit展现出了能够全面碾压c2的性能,什么都不做,就在jvmci里面,用graal jit替换c2,可以得到最多15%的吞吐提升,吞吐就是单位时间内,能够执行的指令数量,吞吐越大,性能越好,graal jit 优于 c2
其次呢,graal还提供了aot功能,graal jit本身也是由graal aot实现的,这个是c++做的openjdk编译器所不具备有的功能,那这一块就更没得比了,c++都没做出来的功能,java实现了
好消息是,graal jit&aot已经决定,一定会并入openjdk,这个项目叫做galahad,加拉哈德,也就是圆桌骑士之一,亚瑟王的传说故事,去找圣杯,graal就是圣杯的意思,法语,加拉哈德就是去找圣杯的骑士之一,这个项目一定会做,但是这是一个比较大的项目,时间跨度可能长达几年甚至十几年,在此之前,graal jit&aot会独立存在,但最终的走势,是确定的,一定会并入openjdk
也就是说java在编译器上,通过用java来取代c++,是一件确定的事,但是在真正完成替换之前,c++实现的c2,还会存在相当长一段时间,但也仅此而已了
其实jdk里面用java替换c++,就算考虑现有的c++代码,比例也已经非常小了,openjdk源码大部分都已经由java实现,这是源码:
GitHub - openjdk/jdk: JDK main-line development https://openjdk.org/projects/jdkc++现在占比不足14%,算上c,占比也不到20%了,就大部分都已经用java实现了,就只有c2等jit编译器还在用c++实现,这也是被替换的重点
当然openjdk是一个非常大的项目,这里面涉及的环节非常多,最终替换掉c++,还是一个比较漫长的过程,但最终趋势是不变的,现在鬼佬也找不到几个愿意写c++的
然后说一下在用java替代c++过程中,可能会遇到的问题
其实问题主要集中在gc和aot上
gc可能带来的问题,以及所需要的优化,都已经做得差不多了,之前说过,zgc直接把暂停时间给压缩到1ms甚至更短,现在操作系统就没有几个能把停顿控制在毫秒级别的,尤其是你手头上的电脑,手机,游戏机等产品,基本上芯片都做不到1ms左右的时间控制
java的时间控制可以低到ns也就是纳秒,但是这要硬件支持才行,但这个不重要,反正1ms以内的gc暂停是完全可以满足现有绝大多数需求的
这里也是老c++程序员吹的一个点,就是在他们从来看不懂,人家鬼佬对于gc优化的进展,在他们眼里,gc暂停永远在几秒以上,遇到这种,看了就屏蔽了吧,因为你说它们真的听不懂吗?不,我觉得它们懂,但是它们为了蹭流量,所以会指鹿为马,所以最好的方式就是将其屏蔽
有人指鹿为马,最好的方式不是去跟他争论,而是直接将其屏蔽
你觉得它真的不懂那是鹿而不是马吗?
不,它懂,但是它会故意装不懂,你永远叫不醒一个装睡的人,在这上面浪费时间毫无必要
c++程序员还在大谈gc就是这样,它不是不懂,它懂,但是它要蹭流量,这就是它的目的
好扯远,说回gc
gc的优化除了把暂停压缩到1ms以内之外,还有一个优化就是aot,因为gc需要内存
程序多占用内存,这个本来也没什么值得说的,有gc当然比没gc的程序要多用一点内存,这不是废话吗?我们写代码,本来就是让机器来做事,如果你连内存都不舍得给机器用,那这不是那句老话说的那样
既要让马儿跑,又不让马吃草
那这个怎么搞?抱歉,你要这么抠的话,建议你从汇编开始写
当然了,虽然内存占用不是很在乎,但是能优化,尤其是能在性能上提供比较大的优化进展的时候,那就会有人会去做这事
那这个比较大的优化就是aot,虽然jit可以在启动之后,通过各种方式,在一定运行时间之后,使得性能达到甚至超过aot之后的代码,但在很多场景下,用户还是希望,能够改进,程序在启动时候的速度,以及内存占用
那这个优化,gc部分能够提供将回收后的内存还给操作系统这一操作,zgc就可以,当然这个是小优化,大优化还是要看aot
java的aot现在是最热门的领域,我甚至都不想加之一
现在java社区活跃的jeps,也就是java的增强,几乎都集中在aot上,关于java全部的增强提案,也就是java社区的核心,在这里:
JEP 0: JEP Index可以看到,ahead of time,也就是aot开头的jeps,开始活跃起来,这些都是
F Dra hotspot / compiler 8313278 Ahead of Time Compilation for the Java Virtual Machine
F Dra hotspot / compiler 8335368 Ahead-of-Time Code Compilation
F Dra hotspot / compiler 8325147 Ahead-of-Time Method Profiling
这些多数是leyden项目的jep也就是java增强,一开始我看他们的意思,是先打算把jit模式下,能够被aot掉的,先给aot掉,比如类的加载,这个是可以先行aot成native代码,然后存到cache缓存中去的,这样在下次启动的时候,就不需要再编译了,这是初步,最终会向着graal aot&jit靠近,这两者最终还是要合流的
那aot的好处就是:启动快,内存占用少
这样手段优化下去之后,你说普通人能够区分得出来aot后的java和c++?我估计你看不出区别来
普通人也不在乎,谁管你用什么编程语言实现的?你用汇编或者脚本写都可以,只要能满足用户需要
作为对比,javafx aot之后的hello world程序,跟qt的hello world,在大小和启动时间上,看不出有太大差异,这个我之前的回答中有对比,有兴趣的自己去找
也就是aot之后,java不管是内存还是启动速度,都可以达到native程序的水平,或者说,aot之后它就是native的,也没什么达到达不到的区别
所以gc和aot的优化下去之后,其实java就完全可以替代c++了,这就是graal的原理
所以对于java的趋势而言,将来就是用java替代c++,不仅更安全,而且代码什么也都更容易书写,更易于阅读和维护,不像c++,连个命名都无法统一,这种代码谁爱看谁去看,我是拒绝阅读,没事不要给自己找罪受,不要没苦硬吃
然后是没有gc的语言,很多人可能就知道一个rust
而我在鬼佬网站上看到的情况,swift比rust更能给c++会心一击,或者说,更适合担任c++终结者的角色
这是twitter上最新的一篇推文,新生浏览器作者们在充分评估了不同c++继承者之后,觉得还是swift最适合
这个观感和体验,跟我个人的经历是一致的,我也觉得swift用起来体验,要超过几乎所有的竞品,java虽然书写上跟swift体验接近甚至更好,但毕竟java的aot还需要时间发育,所以至少在当下,swift的优势应该是其他竞品所没有的,包括rust,尤其是在苹果平台上,优势更加明显
作者关于rust的看法
swift的特点,书写简单,甚至超过python,比python还简单,不信你自己试试,其次呢,性能确实好,因为它目前只支持aot编译,还有就是工具链也比较完善,用mac等苹果工具开发,超级傻瓜化,简直无脑
甚至啊,它在linux和windows上的使用体验,也很棒,挺简单的,也就是跨平台做得挺好
现在就是swift还缺少一个比较方便的类仓库,像java的maven中央仓库那么简单的工具,它还没有
其他的,除了不能jit以外,没什么大的问题,比rust的体验绝对好上不少
就至少不会出现,新人写不出代码的情况,上手很方便,比java复杂一点,但是绝对比rust简单
而且很重要一点,就是swift,它加强了对于c++的互操作性
你看rust用户,到处嚷嚷着让人家把c++写过的代码重写一遍,这恰好是大多数c++用户所不愿意干的事
而swift则很少要求你把c++代码重写,包括苹果自己在内,对于swift的用法建议是
因为swift和c++互操作性较强,所以你不需要一口气把现有的c++代码全部重写,而可以使用渐进式替代的方式
就像那个lady bird浏览器作者说的那样,可以在新功能上先行使用swift来替代c++,然后再逐步将其替换,原有的代码,实在替换不动的,可以先不碰,有空再替换
这样你就不需要像rust用户那样,到处喊着让人家重写代码
这样是不是对于大多数人而言,就更容易接受了?
所以很多用户决定使用swift,这是一个很重要的原因
而且swift提供了一个半自动的gc,也就是arc,同时它也提供了borrow system,就是所有权那些玩意,那对于用户而言,要不要用所有权,就纯粹看你自己的选择了,而不像rust那样,什么都要考虑所有权,对于swift而言,你有使用arc也就是半自动gc的权力
这样操作起来就比rust简单多了
除了lady bird,那个arc浏览器,也已经使用swift做了chromium外层的包装,也已经发布了,我最近都在用arc浏览器,体验不比chrome差,有趣的是,很多windows上的swift工具,都是做浏览器的公司做的,跟做rust那个做firefox的mozilla是同行
这是两个案例,除此之外,最大的成功案例当然就是苹果自己啦,苹果早就在几个场合宣称,要把所有软件全部转入swift编写,包括,但不限于,带ui的软件(也就是app),平台工具,操作系统内核等等
甚至,苹果在前几天发布的大模型中,在Google云上,使用了swift on server编写大模型
所以从苹果的案例中可以看到,苹果将来,是要all in swift的
也就是说,swift的成功案例,有一个是全球市值最大的公司,还有什么比这个成功案例更有说服力?
苹果和Google云上swift的案例,才是最有说服力的证据,告诉你,swift有多可靠
因为苹果自己在用
所以至少在苹果,c++的接替者应该是swift,而非rust或者其他
从编译器角度上看,也可以很容易理解为什么是swift
swift,rust和c++在苹果平台用的clang,一样,这几个都是llvm的前端,后端用的都是llvm
既然后端一样,那么前端的差异仅仅体现在语法上,就不存在说,比如c++(clang)能做,而swift做不了的情况,也就是在功能上几乎是一致的,仅仅是代码语法也就是符号和关键字的差别
而rust用户的问题就在于,他们只看到了rust,而没有看到llvm的其他前端语言
实际上自己动手试一下,就能感觉到,swift比rust简单,当然也更要比c++简单
从java和swift的采用情况看,c++正处于全面围攻之中,几乎所有的,稍微有点影响力的软件,尤其是基础软件,都在想办法去除c++,不同的公司不同的组织不同的人,用法不一样
但是,这个过程确实在推进之中
这个过程很漫长,但是好处是,有人在干这事,这是一个客观存在的事实
就不以普通程序猿的意志为转移,就你不干,你不愿意,它也在发生中
鬼佬会把他们如何做的,发布到网上,油管上,推特上,都有很多,国外也经常会有seminar,也就是座谈会,时不时会开一下
你可以在不同场景中看到鬼佬的做法
各种实际案例等等
这其实才是我写技术回答最重要的来源
其实c++,java,swift,rust这些,本质上都不过是个工具
c++是混乱的根源,实际上c++至少你应该学会区分成msvc++,clang的c++和gcc的c++,以及其它
如果连这个区分都不去做,张嘴就是c++怎样怎样,那多半这人自己都没真正搞懂c++
因为msvc++跟clang的c++它不一样,c++跟c++的差别,比c++跟swift的差别都大
甚至还有把c和c++混为一谈的,这种就更是滑稽了
那关于c++细分之后
msvc++我是不感兴趣的,微软所有的产品我都没兴趣看,msvc++跟c#一样,都是没什么人搞的玩意,windows平台江河日下,份额不断缩减,犹如现在没有多少人搞windows编程一样 ,基于windows的msvc++和c#也没有什么市场前景
如果是clang的c++,那苹果已经告诉你了,我要all in swift,clang爱怎么地怎么地吧,少了苹果,难道clang有谁可以继续依靠?Google?Google也不打算搞c++,Google倒是对java,go和rust更感兴趣,安卓上对kotlin还有flutter/dart更有兴趣,这些工具除了rust,其他几乎都跟java是一样的,选择了gc来管理内存安全,那具体到安卓场景,我觉得flutter/dart也是值得关注的工具,实际上现在dart语法,就是java和swift的混合,早些语法接近java,后面加进去的语法几乎都是swift那边搞过去的,所以如果你会java和swift的话,看dart就太熟悉了,至于kotlin,这个只是个前端,关于编程语言前端(也就是语法)的看法,请参考上述swift部分的论述
至于gcc的c++,没兴趣,功能上被clang完全替代,clang尚且如此,遑论gcc,难道你有什么非要用gcc不可的吗?我没有,你有应用场景,那你自己想办法,不用跟我说,我没兴趣知道
最后,现在ai很火,各种ai芯片都在排队等着上市,比如云端Google的tpu,博通的xpu,客户端的npu,apu这些,之前用英伟达的gpu的时候,cuda和nvcc还有比较多市场
但是以后用什么驱动tpu,npu这些,目前还不十分确定
目前已知的,苹果在Google云上用swift on server驱动了tpu,建立起了苹果的大模型,mac上的npu,m4要等到9月才上市,所以目前未知,但大概率也是swift,因为苹果的战略非常清晰,一直在说all in swift,现在包括metal,core ml,create ml的api文档都已经用swift书写了,因为m4的mac还没上市,所以底层npu api接口还不清楚,但多半还是用swift,只是还没真正放出来,所以不确定
其他的npu啥的,也不清晰,但是我估计也是c,因为c的abi二进制兼容目前是几乎所有编程语言的通用语,就比如你想让java调用swift编写好的函数,那么java和swift就要通过c的abi来沟通,因为java也好,swift也罢,都实现了对c语言的abi二进制兼容,所以它们可以互相用这个方式通信
所以c的重要性要远远超过c++,至少它的abi是非常重要的遗产
所以大部分硬件上市的时候,首先要保证的就是对c的abi兼容
而只要它能提供c的abi兼容的api,那么java等语言,调用起来就毫无难度
过去几年中,java,dart等语言,都实现了对c abi兼容的ffi,甚至都提供了自动生成对应代码的工具,比如java的ffm,dart/flutter的gen_ffi等,然后我看dart/flutter的ffi的roadmap也就是规划啊
dart/flutter着眼于提供对以下语言的兼容保证:c,java,kotlin,obj c和swift
swift的还没做出来,但是已经在roadmap上了,下一步就是开展这方面的工作
dart的选择呢,也能多少回答这个问题,就什么样的工具才是c++的替代?
我的回答是:java & swift