瞎扯淡 为什么 Ruby 这么好用,却从未进入 TIOBE 前三名?

JiangYongKang · 2017年12月30日 · 最后由 jakit 回复于 2018年01月08日 · 5548 次阅读

这是今天的 TIOBE 指数, https://www.tiobe.com/tiobe-index/

达到 TIOBE 前三可不不容易,要有非常难得的历史机遇才可以的。Ruby 不过是借着 Rails 和 Web 开发的大势小火了一把,能够有现在的排名已经不错了,怎么可能进前三。

不跌出前十就不错了,果然跌出了,竟然比 Go 高……

吾辈认为,Ruby 的语言设计是不错的,要不然不会进入前 20。

从实现上,Ruby 2、PHP 5、Perl 5 都是预编译 中间代码,后解释执行的。PHP 7 有 JIT,暂时领先了。

除了 JavaScript 以外,排名靠前的都是符合【企业生产要素】的。

接下来我要说重点: TIOBE 的排行成员变多了,Kotlin Swift Rust 这些东西都加进来了,其实这个排行已经差距不大,Perl - Ruby - ObjC 都是 1.4%,也就是说,你是在要看排名做比较的话,建议看百分比的差距。

例如:PHP 和 Ruby 差距 实际上只有 11%,是“多一点”,如果达到 20% 左右差距,才是“多一些”。

大家再去看看后 20 名(20 名以后的语言),像 Kotlin 还是不错的,Erlang 也有人用,VBScript 很久以前曾经也出现在前 20 内吧。

这个这说明的现象是,语言太多了,越来越多的领域也正在拓展。

如果不是拿语言工具混饭吃的,那么你想学习什么就学什么,所有的语言发展到今天,很多语言的功能、语言周边框架抄来抄去的,基本都均衡了。

正如你可以拿 Python 写网站也可以用 Ruby 写网站也可以用 PHP 写网站也可以用 JavaScript 写网站。

如果想要赚钱,那么就尽可能选择靠前、符合你身边市场需求的。

补充: 上文【企业生产要素】,吾辈认为 Java 有很成熟的 VM,你不用考虑 空间 随便你抽象,反正内存效率、编译也会优化你不用担心。如果你需要手动管理内存的高效 IO 开发(涉及系统调用比较多的),C / C++ 是不错的选择。Python 是啥都不用考虑,快速敏捷同时保证范式基本一致(以便尽可能实现企业统一代码思想好维护)的。

jakit 回复

为啥 Ruby VM 结合了 Java 的 Hotspot 和 Python 的 Interpreter?感觉都没啥关系啊?

dsh0416 回复

按照现代的解释器来讲,其实没什么区别,Hotspot 主要是引入 JIT。

以前有区别,是因为那时候 Ruby 没有编译器。

jakit 回复

Ruby 的官方实现 JIT 现在还是没有的,MJIT 目前还在比较初步的开发状态。可能 2020 年前才有可能加。Python 是 1991 年发布的最早版本,Ruby 是 1995 年,Java JDK 1.0 是 1996 年。Ruby 随着 YARV 的引入,现在也可以编译到 Bytecode,也可以说是某种意义的编译语言了,但是和 Java Hotspot 区别还是比较大的。要是说像 Python,我就更想不出什么原因了。

如果不是 VM 层面,而是语言层面,倒是讲得通一些。Ruby Python 和 Java 肯定都有不少像的地方。Ruby 不严谨地来看,特别是早年可以看成是 LISP + 面向对象 + 减少括号 + Perl 里的字符串。Java 从 LISP 和 Smalltalk 里学了很多东西,而 Python 也是一门很像 LISP 的语言。。。那么 Ruby 和他们像不如说是大家都像 Lisp 吧。

这么一想,其实还是挺推荐 Rubyist 去接触一下 LISP,可能会对 Ruby 的一些设计理解得深刻许多。LISP 是一门 1958 年的语言,是世界历史第二悠久的高级语言,但是确实有很多很有远见的设计。

dsh0416 回复

差不多这个意思,所以 Ruby 才会被 Lua 甩 N 条街,还有 JavaScript 各大引擎。。。一个简单的斐波那契 40,Lua 是秒完成,Ruby。。。

要是什么时候 Ruby JIT 完成了,就追上来了

jakit 回复

你先等等。。。

标准 Lua 是没有 JIT 的

9 楼 已删除
jasl 回复

我知道 标准 Lua 是没有 JIT 的,我说的是 Lua JIT 的 Lua JIT

jakit 回复

我再问你个问题吧。。。什么时候 JIT 会慢...

jakit 回复

你先等等。。。

如果 JIT 对 Ruby 那么重要,对标 LuaJIT,Ruby 也有已经实现了 JIT 的 JRuby 和 Rubinius 啊。。。

JRuby 倒是去年搞了个 GraalVM + TruffleRuby,真的还挺快的。但还是风声大雨点小。

最近 Rubinius 还把 JIT 从实现中移走了🤦‍♀️

13 楼 已删除
jasl 回复

For bytecode which is executed only a few times, this saves the compilation time and reduces the initial latency; for frequently executed bytecode, JIT compilation is used to run at high speed, after an initial phase of slow interpretation. Additionally, since a program spends most time executing a minority of its code, the reduced compilation time is significant. Finally, during the initial code interpretation, execution statistics can be collected before compilation, which helps to perform better optimization

没有啦,至少人家就事论事的话,如果能最后达成共识,也是好事啊。

dsh0416 回复

嗯,可能我没了解到那种程度,但是如果抛砖引玉的大家说出自己知道的,也是不错的。我说的不一定对,只是站在目前所了解的程度,发表个人想法。

如果有更好、更深入的了解,吾辈愿意学习。

jakit 回复

那么你觉得你举的例子跟 JIT 有关么

jasl 回复

为啥我每次都被你们抓着不放呢,我只是发表个人看法,我没说过我的想法必须是正确的,我也没要求所有人都按照我的想法作为标准。

这种情况很多,比如有时候我翻翻以前很多人对 macOS 网络、IO 支持很差的说法,其实是很多人对 CFNetwork、IOKit、kqueue、GCD 没有深入了解。

知乎上面还有很多 13 年前的老帖子,比如一些人对 Python 的理解是不够完整,仅仅说一些很肤浅的答案,但是那个人、那个时候还没有了解到其它更多的资源。这时候你是不是要在下面回复一大串把别人说得全错,自己全对为止?

包括我以前读书时的一些老师,课堂上也会提一些学生不以为然的一些说法,其实有些同学是从别的领域了解过了。

另外,我又不是给大家上课,我只是谈谈我的看法,仅此而已。

我总是发现一个规律:

姜叔叔每次都把我说得不足的地方挑出来去证明你的威严。

19 楼 已删除
jakit 回复

话说出来是给人看的,技术交流对就是对,错就是错,别人有没有深入了解和你说话对错没有关系。

你的规律显然也是错的,挑出你的错是为你好,证明不了我的威严。

jasl 回复

好好好,我怕了,这回我真的怕了。

不讨论人,姜叔叔你把你对 JIT 的理解说一下,可以吧。

反正我没写过 JIT,我只写过一个简单的 LL 左递归的推断方式的解释器。

虚拟机的话,大致从书上看过源码了解基本实现,当初学生时代想去实践,但力与时间不足。

根据补充,新的回复已经在楼下更新

我大 Matlab 竟然第十了 覺得很不實在。。。

jakit 回复

你有什么好怕的,谨慎评论自己不熟悉的东西不是最基本的么?或者你要验证自己的观点对不对,作为问题问出来,你每次遇到的尴尬就都不存在。在者,提醒你错了,你可以自己去补全知识,也可以听取正确的观点。

可现在是什么样的呢?反驳你,你就摆出一副被迫害的样子,这不是健康的交流方式

jasl 回复

嗯嗯嗯,好好好,要健康

jasl 回复

姜叔叔都不回我问题,那我自己回答吧,JIT 的另一面就是 AOT,说 Android Dalvik 是 JIT,那么 Android ART 就是 AOT(其实也并不是,准确来说是先 AOT,后继续 JIT 优化)。

对手机关注比较高的人,说到这里应该都会反应过来了。

AOT 是 Ahead of Time,提前编译好。

JIT 就是动态的编译器,根据代码执行状况产生的 profile,找到频繁执行的代码再去优化编译成 native code 再跑。

但是,每次都运行的时候再 gen code 肯定效率会低一些的。如果你的程序结构不合理,频繁运行的部分代码不能触发 JIT,那么 JIT 反而是有害的,消耗了编译时间产生 native code 你后面却不调用它了。

但是 AOT 编译之后就很难优化了,不灵活。

C / C++ 的 gcc 编译器就像 AOT,一次编译完之后就是运行。

LLVM 则有 JIT,Rubinius 就是借助 LLVM IR 实现的 JIT

C / C++ 有些场合不如 Hotspot JIT 快,比如方法缓存、调用命中率,这个有点像 iOS 的 ObjC Runtime,每个对象都有自己的方法 cache,方便下一次调用同样方法的时候优先出来。这时候 C / C++ 程序执行就像走路是按原路走的,但是 JIT 就已经找到捷径绕过去了。

补充: 现在的 JVM 不仅仅只有 JIT,还有一种叫做动态编译优化,就是 JIT gen native code 之后继续优化成效率更高的 native code,比如 JRocket

简单来说: 这些其实在很高并发的场合比如你频繁请求 /index.do 然后调用 route 的相应方法产生了方法编译缓存之后才有很高奏效。如果你的网站根本没人看,就你自己一个人一天点一下,或者页面过于分散然后设置的缓存过小,那反而更慢了,因为方法缓存是 LRU 或时效(根据配置)有效的。(这讨论的是虚拟机优化部分的内容了)

26 楼 已删除

MRI 现在的情况就是 old old JVM,等它成为 Hotspot 或更好的 Hotspot 的时候,基本就成熟了。

路还很远,并行问题说好了在 3x3 实现的:optimize / remove GIL

MJIT 已经在 Open 状态了,等待 merge https://github.com/ruby/ruby/pull/1782

jakit 回复

哭了,装 x 失败的典型反例。你不要老是一知半解就出来秀啊,碰到比你更懂的人不是分分钟就被打脸了吗?

29 楼 已删除

如果你不确定,一定要说出来!一个听起来权威的错误回复比没有还要糟,别因为听起来像个专家很好玩,就给别人乱指路。要谦虚和诚实,给提问者与同行都树个好榜样。

如何更好地回答问题

Rei 回复

Thank you very much!!!

其实就是表达方式,我换下表达方式就好了啦

LZ 先回答我哪一年排行前三的语言中有非常好用的呢?

jakit 回复

不知道你的斐波那契数列是怎么写的?是递归算法么?递归 lua 要比 ruby 快是必然的,因为 lua 有尾递归优化,试试看看动态规划的算法实现下,结果就不一定了

geekerzp 回复

https://fengmk2.com/blog/2011/fibonacci/nodejs-python-php-ruby-lua.html

要优化,方式多了去了,不一定动态规划那么长远,加一个作用域长一点的变量就好了,比如 @@,我以前习惯用 Perl,那么 Perl 的话,一个 Memoize 就可以了,消耗点空间,Rubygems 里面也有 Memoize。

这些比较还是有一定价值的,起码可以说明一门语言的编译器开发组织是否继续维护,是否跟上时代。

Ruby 是有尾递归优化的,只是默认没打开,RubyVM::InstructionSequence.compile_option 里面有 stack_cache。

用 Ruby 嘛,自己爽就行了,上不上 TIOBE 前几又咋了呢。

想進入前三名是不是有一點異想天開了?XD

你可以看到 15 年前開始,頭三 Java C C++ 基本上只是上下對調。我不敢說未來 10 年,但我敢相信未來五年內這個情況也不會改變。

數字上從另一種角度看,全球 35 億 Smartphone 用戶,7.5 億 iOS 用戶,佔全球 Apps 總營業額大約 40%,整體出貨量及使用率遠超整個 PC 市場,但 Objective C + Swift 卻只有 ~ 3%,而 Ruby 卻有他的一半,1.5%!

所以那個比率其實沒有什麼參考價值。但可以肯定的是 Ruby = Rails , 在整體上市場上一定比其他語言少。要 Ruby 長注頭十,必須在其他領域有所突破才行。

能进前 10 就很不错了,这个位置也经常保不住的,现在更难了。

jakit 回复

java 不仅仅是 vm 还有整个庞大的生态 这是 ruby 这种脚本语言 不能比的 就企业来说 追求的是效益。就我个人来看 ruby 这种语言是不适合多人协作的,尤其是人员水平不可预测的情况下。不过 ruby 做到现在已经很不错了 毕竟没有大厂支持

zouyu 回复

没办法,Ruby 从社会影响力远远不及 Java,Solaris 是 Java 口味吧 Android 也是 Java 口味吧(Kotlin 也是 JVM 口味的),数不胜数,而且那些都是现成并且发展、运作了很久的。

你说的不适合多人协作,就是我故意不在我前些文章提出来的,动态语言本身就是让你边跑边重新赋值指针或引用来达到改变类型,可以更灵活地即时使用操作所指向或引用新的类型。

这些在 C void * 的一些文献(各书籍都讨论过)讨论过是很危险的,但是有运行时的语言基本都有类型系统,这样就可以弥补了反射的时候因为找不到方法所存在的内存地址而导致计算机崩溃,个人观点,运行时的目的就是为了抽象出让你安全向一个对象发送消息之后能够保证不 segment fault 而是在抽象机制保护下抛出异常。

void * 在某些场景会是一种 bad practice,迫不得已或者使用系统硬件编程的时候要用。因为你无法推测前程序员那么多 void cast to what。

请参考 Bjarne Stroustrup 提到的观点:http://www.stroustrup.com/bs_faq.html#unsafe

动态类型语言就像到处是 ObjC 的 id,Java 的 Object,想象一下 Ruby 所有的便利情都是 Object var_name 的定义,实际类型从代码表达上不够明确的,存在代码可测试性、可便于观察和维护的问题。

但是作为高级开发者,他们拥有比较高的编程素养,自己会 is_a? 再去处理,保证程序变得井然有序。

所以,吾辈认为 Ruby 实际上是自顶向下思维方式,先实现个大概,再去一步步确定和细分。

然后,我们再从动态基础上强弱类型再进行细分讨论:

A 派别就是 PHP 和 Perl,风格是 C void * 那样的,到处充满了莫名其妙的强制类型转换不优雅的(人类通常思维导向而不是计算机思维导向,在《Perl 入门指南》书里面有提及,但记不太清楚了)隐式转换,而且很多操作不区分类型。在运算不符合条件,某些场景都允许通过并且“人性化处理”,让人们安心地不管计算机基础而去像各种奇葩的客户需求,把东西做成不规则、不考虑计算机能否实现或者原本逻辑该怎样然后歪曲的。

在《Perl 入门经典》贝壳珍珠封面的书里面就列举了很多:你写的逻辑上有很多不兼容的类型,但由于解释器为你的代码做了神奇的转换,你看起来写对了的程序却得出神奇错误结果的陷阱。

结合了 动态 特性后,吾辈认为 PHP 成为了一门名副其实的变态语言。这样的语言肯定是非常考虑书写者的内心感受,让一些连最基础的类型是什么都不懂的人都能完成编程任务。

B 派别就是 Ruby,风格就是 Java 那样遵循类型规则的语言,虽然可以转换类型,但是得做安全转换,运行时不会莫名其妙把你类型瞎转的,一切方法呼叫和传递都是是有依据的,是可测试的。

结合了 动态 特之后,Ruby 既能享受到 Java 的好处还能享受到动态的便利。

------分割线---------

在当下浮躁的社会中,一切以效益利益至上,谁会去管你优雅不优雅,正确不正确。

我的领导,他只管我把今天的事情完成,恨不得上 PHP 今天一天哪就把一个项目做完,明天就上线,产生经济效益。

然后高端层次的大企业,他们有非常稳定的秩序,需要像 Java 那样不太灵活但是严谨的语言来起到规范人的编码约束,才能 hold 得住一个很大的团队。

前不久的时候,我提出了个疑问:

有钱人都去买苹果,没钱人都去买小米

辣么,谁买高不成低不就的中端手机?

jjym 回复

Java 挺好用的

jjym 回复

C/C++ 用不好,但是我也觉得它们是很好用的

jakit 回复

我觉得可能是他们百度了一下编程语言,然后看见第一个是 java 然后“哦 有个叫 java 的编程语言啊 那选就 java 吧”

geekerzp 回复

ruby 也有尾递归,只是要手动开启~~

adamshen 回复

@jakit 只是在说他自己的想法,像我这样一个外行人,一样看的很 high, 对不对,反而不重要了,自己也会有评判的标准,对吧?

@jakit 说真的,不用太纠结 TIOBE 排名。 只关注相应领域的语言就好。如果写网站,那么只看 Java Python PHP Ruby 就好。 TIOBE 排名前十的语言中,C C++ VB.net R,这些都写不了网站。不用去理了。

tiseheaini 回复

谢谢理解,之前的帖子纯粹是卖萌的~

爱用啥用啥,每个人都自己的风格,就像相机那么多,买哪个品牌不好,过分强调个性不太好。

JiangYongKang 关闭了讨论。 07月15日 13:46
需要 登录 后方可回复, 如果你还没有账号请 注册新账号