• 另外,GCD - libdispatch 也是类似实现的,效率超高,不过,我輩认为,Ruby MJIT 还没上呢,而且 GIL 没彻底解决之前,没什么好兴奋的。

  • 听起来就像是当初困扰我的【打算用 C 线程和 Ruby 对象关联,想绕开 GIL 实现并行,但是由于 GC leak 又串不到一起】的问题,有人出来解决了。

  • 按照这么说,主流操作系统都是 blocking 的,每秒处理的指令集就那么多,而且核心都是数得出来的。

    后续 non-block 都是抽象的,无论 批处理还是分时还是其它。

    真正面对的问题是:找到问题对应最高效的解决方式。

  • 那个是 ActiveSupport::Memoizable 的拆分版

    其实占用内存还并不是最优解,也没有解决问题而是绕开了问题,以前有一个 256M 内存的机器,没挂 swap 的情况下 cpan 一下,在 extract 索引包的时候就炸了,OOM 错误。

    真正要解决本质问题,我觉得要么就从 Ruby 更高效的调用方法去写,比如 for in / times 改成 while,还有对象避免 GC 对象复用。要么干脆 C 去用扩展来实现,至少可预算大 O 复杂度,虽然不如汇编能看出来跑了几个指令。

    文章的思路算是 Go extension 了

    但是你都这么来实现了,为什么项目一开始就不去用 Go 来写呢?

    提一个题外话,用动态的系统(这里指比如 RubyVM)去写一些需要持久运行的东西(比如 server),一来行为不好确定(未来后天行为变了呢),二来出 bug 了要动态反查,如果要把 Perl / PHP 加入讨论,那更恶心了,我读了 Perl DBI / DBM 部分的源码,那真心是狗呕一样的一坨,self “内置” 了很多东西,正如 PHP CI 框架 $this 隐晦了 class_loader,很多东西变得隐晦、不可预测,几乎只有写代码的那个人,自己才清楚这个模块结构是怎样的。

    但是,动态虽绕开了 “显” 问题带来了 “隐” 问题,但总不可能让你把方案都完全确定了再写代码。如果用静态的系统去实现一些方案不确定的东西(姑且称为 “隐” 问题),有很多方案上需要细化动态处理的东西,你需要拿静态去模拟和抽象,静态的系统会被这些尚未探索明确的问题卡住,而且调整起来也很困难除非足够人手(带来的人力成本)。

    我輩只是想说,这种事情其实是矛盾的,只能说各有千秋。

    很多 Cpp 程序猿,可能后续会把 lua 学了以便自己在某些开发上能减轻负担。很多脚本程序猿,可能后续会把 C 学了写扩展,一个道理。Java 这种有商业公司养得白白胖胖的可以另外说(不过最近鉴于 Oracle 的事情,有点不好说了)。

    光吃零食,肚子还是饿,可能还是会吃点正餐填一下肚子的。光吃正餐,嘴巴有点馋,可能还是会吃一点零食满足嘴馋。爱怎么吃怎么吃。

    觉得 Ruby 薯片吃不饱,想把 Go 饭团搅进去充饥也是没问题的。

  • 前不久买了英文版,啃得慢,上班忙,放一边了。中文版现在终于有了,求书

  • 他们跟你说的是两码事,其实我在 OJ 的时候发现了这些问题,用 for in 跟 while 完全性能是两码事,原因具体看红放大镜书里面有解释,while 效率是比较高的。

    他们用 times 的方式处理,a, b 是不会再在一个堆栈继续创建对象的,而你的 fib(n) 里面的 n 是继续创建对象的。在 Perl 入门经典那本书,就建议用 Memoize.pm 模块优化,消耗内存换性能,个人观点其实也就是预 malloc。Rubygems 里面也有 Memoize gem,可以搜搜看。

    怎么说呢,这个其实不是脚本语言和编译型语言的区别的问题,但是如果不打算非常认知到底什么原因,然而这样理解暂时也不是问题,也没毛病。

    这个应该是 C++ / Go 这种接近 Raw 处理的语言处理东西的方式的区别,Ruby 一个 for in 其实代入了一个 block 到 each,然后每个对象创建产生了大量的系统调用,本来 Ruby 创建对象就有大量的调用过程、还有方法调用也是耗时的事情,还有 GC 比起 Go 的内存管理差很远的,区别就在这里。

    C++ 写一个算法,大概 O 几 基本上内心都有个数,但是 Ruby / Python 实际上掺和了 Object 的一些调用,一些语法也具有隐式处理。

    所以本质上是没有可比性的,要说服的话,你应该找那种 Go / C++ 和 Ruby 在调用上用了几个指令接近的方式,但是我只能说,不太可能,我看了 Go 的源码,底层很多实现感觉几乎是拿着 Intel / AMD 处理器的文档对着优化过的。。。

    详看它的运行时 https://github.com/golang/go/tree/master/src/runtime

  • 前后端分裂 at 2018年01月21日

    赞同!!!一年前看过 tk 你的前端开发工作栈,然后就开始过一段时间 SPA 的修行,我把公司的系统做成了前端独立的全栈应用。其实也就是上文说的那种

    实际上 SPA 根本没办法照顾 SEO,另外 React 也是因为考虑到整体化全栈方案其实很不靠谱所以更好的方案是 Components 组合而不是像 ExtJS 整块下来。

    同构的方案不是小公司随便拿来玩的

    Node.js - Express.js 中间层做首屏渲染很棒,实际上 checksum 一点都不好玩。而且,你得有一个很强大的微服务的后端,就是说,你公司得有 Hadoop 结构的团队(我的意思是你的项目已经很大了,Web 端已经支撑不住了,开始出现了微服务,然后 Hadoop 作为 Hibernate 支撑高 IO 数据),最好还要上 Apache Kafka。

    然而,并不是每个公司都是 BAT 给时间成本随便玩弄这些东西的。

    另外确定项目有这么大么?

    推测 LZ 的团队模型是 Ruby + JS,吾辈认为,中间件同构适合的模型是 Java / C++ RPC + 消息中间件 + 消费者端(也就是 Express + React 渲染组合)。

    据逼乎相关贴子了解,Amazon 用的就是 Java RPC + 消息中间件 + 消费者(RoR)的模式做某一块的业务。

    首先如果用的是 Rails,下文就不用说了。。。Rails 就只是消费者端的一块,基本同一层的东西,JS 还搞一遍,不打架才怪。

    另外,最近关注了 PHP / Rails 排行掉下来的一些评价,反正吾辈观点是几个巨头企业逐渐用 Micro Service 取代了 SOA,就是用 Java / C++ 来书写微服务,这样跑逻辑更快,然后输出给前端,Amazon 还在用 Ruby,只是 Ruby 请求微服务拿到了数据之后渲染网页,做快速开发。

    大企业人力分配明确,独立岗位,如果还是拿 Rails REST 对比起 Node.js 同构,也就比如 Express.js request 微服务然后并且渲染首页优化 SEO,然后同时也提供 Components 的 Data 流,这才是同构比较适合的场景。

    微服务的趋势,是所有前端、后端独立招聘岗位的企业都可能或应该做的事情。

    以上纯属个人观点,有更好想法可以修正

  • 前后端分裂 at 2018年01月12日

    能理解前辈内心一肚子气,实际上社会每个人都不服输的,没有人会示弱。

    前端过度分离才是失控,但是如果就一个简单同构而已,学习成本也不算太高。

    就像选择多门语言 Fusion 开发,其实两三门在一起沟通,都行。只要不是把 Erlang / Haskell / Ocaml / Clojure 甚至 BrainFuck 一起混到项目里,吾辈认为都是没关系的。

    而且调用结构得自然,你选择了这个方案,那么,就意味着你得负责到底,跟同事之间讨论的时候就得好好沟通怎么对接。

    对于项目交接的事情,我觉得,不是外包公司那种写一个代码公共模板,然后大家必须得按着这个步骤继续写,搞得跟军训一样,最后是机械劳动,都是不好维护的。

    因为每个人多多少少都会有自己的代码风格,然后别人看了可能是没办法理解的。

    你想要规范,可以,那你只能让开发者以固定代码风格、固定设计模式,甚至最好就是贴一个样板,全部复制粘贴这个来改。但是没人会愿意这样的。这个你在软件外包公司可以做量产的时候用,外包公司反正就是赚一笔钱,做体力活。但是一般开发者都是有情绪的人,他们不乐意的。

    而且那样子也彻底贬低了开发者的智商,应该说直接无视了员工的智商。

    一个工人不管他用什么锤子干活,只要他不是整天花式整墙极端分子,以至于其他工人没办法跟他的墙打通,他要是老老实实的抡起锤子工作,好好跟其他工人沟通,必要时打通通道,还是没问题的。

    虽然我也在前端奋斗过一段时间,同不喜欢 node 一大波的东西在不同的 目录下放了一堆包。此时会想到 Monolith 的好处,但是事情并没有绝对,完全 Monolith 那就是 M$ 那种整套商业解决方案了。

    我目前的情况跟前辈 “应用总有一天会变复杂” 刚好相反,领导是项目都没做,就直接 “你总有一天生病,让你同事帮你改代码的”,然而我每次生病都是不敢请整天假,请个半天,几个小时,至今年假都没休过,更从来没有因为代码好不好维护。

    前者过于开放,后者过于保守。

    更贱的事情是,我领导不同意我用混合语言方案,结果我还是忍了一段时间,采用了 PHP,结果写 Laravel 的某个同事说两套 PHP curl 着不好对接,怪怪的,因为分成了两套项目,然后让我加进去跟他一起写 L,但是我压根不打算使用它。

    然后,这次是重点,另一个同事跟他一起用 Laravel,然而那个人写的东西他也有看法,觉得是别人代码风格啦、模块不应该自己又写一遍啦啥的啦,用法啦。非得别人跟他同调

    人就是这么犯贱的,别人的代码都是有问题的。

  • 前后端分裂 at 2018年01月10日

    然而 ASP.NET 已经有了这种东西~

    微软作为大厂一开始就有野心全栈化,其实微软哪里不打算全栈了,有数据库,又有办公全家桶,还有自己的语言、编译器,数不清啊……

    话说是 05 年后,Ruby(Rails) 这种作为 Java 的挑战者挑战商业权威 Sun,然后那时候很多人鼓吹说喜欢用 Linux 啦(王垠),说 FVWM 多漂亮,在学校宿舍就他用着鄙视其他用 Windows 2000 的童鞋啦~

    再后来就是开源鄙视闭源,鼓吹开源,然而,我最近在 mac 上买了几款软件,都是闭源付费的。因为开源的很多东西真的不如闭源的体验好,我宁可花钱 3000 买 Photoshop 也比 绘图压感不强、各种地方都没经过很多很多专业从事插画人员使用然后报告还有优化而纯粹一帮码农自认为观点上产出的 gimp 要好很多。

    因为我现在需要的是画插画(需求),而不是看 GIMP 的源码去编写可持续使用的绘图软件,

    Blender(开源)和 Maya(闭源)比较

    Maya 是现行工业标准,什么叫「工业标准」,就是经过严格的生产环境考验,足够支持工业生产需求的标准化方案。Blender 是很酷,但不足以支持一整套工业生产流程。不是 Blender 做不到,而是开发者和用户基数不够大,开源社区的开发模式并不能保证其架构和 API 的稳定性。举个简单的例子,在硬件渲染上同时提供接口支持 HLSL/GLSL/Cg 的扩展支持,就足够耗费很多人的精力了(不知道现在 Blender 有没有支持 DirectX,貌似还没有),有没有就完全看社区的心情了。

    摘自 https://www.zhihu.com/question/21975571/answer/144690708

    一般人会认为,你总不能拿一个玩具放到公司里面给大量生产的美工用吧?但也不一定,如果你在为公司特有美术、业务情况维护和开发 Blender、GIMP 然后在公司内部用,倒是不错的主意!

    小辈认为没有任何绝对的好处(完全都是好处?),也没啥绝对的坏处(一无是处?)。

    工具是用来解决问题的,每个人按照自己的意愿,拿工具完成就好了,你跟别的工人在工地干活,整天喷人家的锤子多烂多垃圾,搞得人家今天没办法干活才是问题。道不同不相为谋,跟自己意愿更好的伙伴一起。

  • 前后端分裂 at 2018年01月08日

    没错的,所以我老板的意见很大,真相是为了完成一个任务,自己过于发挥个性了

    其实每个人都有自己的独立思考、实现方式,有些人喜欢 DIY,有些人不喜欢 DIY,然后有些人喜欢拼接 SQL 完成任务。

    我前同事不喜欢 ORM、AR(ActiveRecord),把一件事情写成 SQL 的 swich / if 去条件拼接来完成。每次需要新的数据的时候,第一件事是手动创建表,然后再在逻辑中加入相关表查询的 SQL 代码。。。

    但是别人看着很脑大,谁知道他拼接着起什么作用,干嘛来着。

    前同事没学过 Ruby、Java 属于老的基本只接触 PHP 员工,ORM 都没用过也没了解过,甚至可能心态上也不愿意接受(之前跟他提过但是他一开始是不愿意接受,后来我把公司某一套系统跟他合作的时候一步步做完,引导他不要用 MySQL 存他 PHP 配置啥的都丢进去,引导他自己独立学会组织数据成结构成对象,适配配置和模型,而不是整天摆弄数组【由于 PHP 数组是 Array 和 Map / Hash 的组合体过于强大,让一些开发者感受到的是表面而没有深入】)。

    硬是要区分 MVC 是没意义的,后端的 V 站在 API 的角度观点,那就是前端的数据源,那么就是前端的 M,思维是可以切过来的。

    我曾经和前同事因为 ORM 的事情发生过争吵,他不让我碰他 PHP 的 M,只让我写 C 和 V,然后闹翻了,我干脆连 PHP 都不写了,把 ORM 全丢到 前端 去独立实现了。

    最后任务还是完成了,是因为在过后领导批评让我好好如果把自己好的想法怎么让别人理解。然后那个同事在我多次把自己的设计稍微推动,然后也尽可能不排斥(尊重)别人站在别人观点哪怕不太正确的理解,毕竟实际实现的是人家不是你自己,不能太过分了。所以别人通过学习,还是把我的思维串起来了,事情做完了。

  • 前后端分裂 at 2018年01月08日

    呵呵哒,前辈你得仔细观察一下,细微之处透露着小心思。

    我是前端全栈拿 JS + Ruby 混合用,后端的只用 PHP,所以开发方案是 JS + Ruby <-> Laravel / CI。

    然后由于 Ruby 不是 JS,没法同构,所以我才阐述了:

    所以我带上自己的 amber-kit 之后模型是这样子的:
    前端 Page(Input) + (View(Static) + Data(Input) -> Component)

    其实是 SPA + Components 混合结构,然后由中间层路由。

    扯那么多,其实该做的事情不过三件事情:M V C,我负责前端 + 中间层,把 M V C 都拿走了,而且还做成了首屏渲染,SEO 还有问题?那么其他人就只剩下 DAO 了,咿呀哈哈哈哈~ 😹

    其实过后会发现那个 DAO 也变的多余了,没意义。

    但也是有用的,因为其他人的 DAO 的数据是用在另一个网站的,我只是让它暴露几个接口,就像分几个资源过来我这边取数据,我可以不管数据库怎么实现。

    这些都不是重点

    你也可以认为要求全栈,说白了就是独立完成,但是独立完成的部分是按照【功能】划分的,比如它别的网站的东西,我管不着呀。。。

    我没有偏要用一门语言去实现所谓同构的同构,只是为了达到这项目的,我用我喜爱的语言、工具做这项任务。

    所以我建议说:

    分工应该按照功能、模块分配给不同部门(大公司)或员工(小公司)执行,而不是按框架画饼甩出去然后你们一起做吧

    作为老板、管理者,分布任务才是重要的,作为开发者,管你全不全栈,你把部分功能为了 SEO 丢到后端去写好,SPA 全静态也好,要是 Rails 全栈也好,屁大点事,因为完全是具体实现方案。

    我意识到前后不可分离,其实本来就是一个客户端,一个客户端包括了界面、数据、存储,因为网络时代的原因,以前浏览器没办法达到独立客户端开发的素质,所以依赖于让 “后端” 把界面配置(HTML 发明的目的)和界面修饰(CSS 发明的目的)推送过来,然后前端也没办法存储加上数据分发问题,所以当初是集中存储,把这些合起来,就像是 后端语言 + Database -> HTML Output & CSS Output

    不要开圣战,开了就没办法做了。

    我从前辈的文章所看到的问题是,你们没有根据任务拆离,而是为了一两件破事把任务过度发散了。

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

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

  • 前后端分裂 at 2018年01月08日

    我的理解,以前的网站开发:

    View render Data mixed

    这个年代不区分前后端,页面都是动态或者静态的,就是有无脚本改动过的区别


    后续演变:

    View render + Data (Separated)

    开始拆分模板和数据 ajax 异步,让页面先加载


    后续演变(分支一):

    前端 Page(Static) + Data(Input) -> SPA

    后端 Data(Output)

    这个是 SPA 的前端但页面客户端化的思想


    后续演变(分支二):

    前端 View(Input) + Data(Input) -> Component

    后端 View(Output) + Data(Output)

    SPA 太死板了,React 提出视图组件化(Component)


    后续的演变 (Current):

    前端 View(Input) + Data(Input) -> Component (与中间层 Sync & Checksum)

    中间层 (前端占据) View(Output) + Data(Input & Output) -> Component (与前端 Sync & Checksum)

    后端 Data(Output)

    Current line 解决什么问题呢?就是解决不再让后端管制、约束前端开发者,前端开发者更自由、灵活自己去拿到数据后又自己去按照自己思维再二次分配,也更自由觉得像怎么做 View 自己管理,简单来说就是解决前端开发者不想用你的后端 Rails 来渲染它的 View。

    其实我在我自己的工作环境就是这样的。。。我特别不喜欢 PHP 去捣鼓我的 View,但是项目前期我又没那么多时间搞中间层,就变成了上面的 SPA:

    前端 Page(Static) + Data(Input) -> SPA

    后端 Data(Output)

    当初我发明 amber-kit,其实是我自己用的来做 中间层的。。。中间层对移动端也有好处,可以二次分发、整理数据,把不同的数据源聚合到自己前端(不论移动还是 Web 前端)组合的独立开来自由版本分发迭代的数据源。

    所以我带上自己的 amber-kit 之后模型是这样子的:

    前端 Page(Input) + (View(Static) + Data(Input) -> Component)

    中间层(前端占据)Page(Output) + Data(Input & Output)

    后端 Data(Output)

    其中,我负责前端 + 中间层的工作,但是老总特别不满,尤其我用的是 Ruby 来写,老总暴戾,说多么不好招人,因此经常在团队面前说我多另类啦,怪异啦,为了追寻某种风格啦。


    这些设计,本质是为了让自己在自己的工作中有更多的主动权,自己的设计权。

    想想看,如果前端只是为了写个 JS 控件,完全被动性地变成了配合后端输出成什么样的 HTML 再自己去把数据渲染。沟通上会有困难,因为前端开发不一定清楚后端渲染的规则、数据的规则,而且有点变成了后端的下属,人家给什么就怎么做,稍微麻烦了的话,就很容易引发矛盾了。如果是独立岗位的话,一定受不了的。

  • 前后端分裂 at 2018年01月08日

    react 和 vue 同构,是为了 components 前后一致,一套代码多处执行,同构组合在一起,在同一个 proj,两端分别渲染出来的这个,下一步这个东西也是我自己预先定义的会反向跟后端按照预定的功能行为同步、校验。

    吾辈认为,总想着一套代码多处执行,那肯定有问题。自己和自己分别在不同端的校验,该多麻烦。我认为以前 ASP 啥的也有一些自动生成脚本,反正生成的东西会跟服务端匹配,但是这个东西很依赖 IE,必须微软方案一套从头到尾下来。

    我想说的就是这个,而没说 Rails 搞同构。只是觉得大方案都求全求同构,那是不现实的。

    我已经听到有前端开发说不想碰 Node.js Server 了,他们想专注于处理交互(这也是前端职位的本意)

    很正常,我觉得分工应该按照功能、模块分配给不同部门(大公司)或员工(小公司)执行,而不是按框架画饼甩出去然后你们一起做吧

  • 前后端分裂 at 2018年01月07日

    过度抽象是不好的,但是我觉得设计出来的人,就得负责到底。

    以前一个变量传递就能完成的事情,现在要写一个 API。需求没完成,没有人会是轻松的。

    我想到的是不是前端把啥数据、自己能做的逻辑都丢给后端开发了,然后自己只是打算拿数据都不做点事情,然后后端逻辑过于变态,把后端累死了?

    我觉得到最后,前端会嫌弃后端太不给力了,来来来,咱们自己连数据库算了,啊咧?这不是 Win32 MFC + ODBC 年代的 方式吗?

    补充: 把前端框架放到后端渲染,开发难度指数上升,这难道不是 Rails 把 webpack 混进来的害处吗?吾辈当初不太认可 Rails 巨石思想,就是啥都包含进来,还一起构建,这样多管闲事,复杂度很高的。

  • Ruby 现在是不是很尴尬 at 2018年01月06日

    我今天本来写了个帖子的,后来忘了 Submit

    姜叔叔 @jasl #12 楼的答案,其实 已经接近我想说的

    我当初介绍 Ruby 好处的时候,其实有一个核心的地方就是【它是动态的】,这一点在所有强类型语言中都能 get 到他们没有的好处。

    ActiveRecord、元编程的核心在于【动态注入】。

    然而,所有的静态编译语言,在编译的时候都要做一件事情:行为检查。

    这件事情,让静态语言没办法动态地为一个对象添加方法同时能在后续的代码中写出直面调用的代码。

    比如,ObjC 允许你在 Runtime 注入一些东西,你可以给 obj 注入 getAttribute 到 Runtime,但是你在代码中写 [obj getAttribute] 是直接编译不过,告诉你 getAttribute method 不存在的。

    Ruby 作为动态语言,就像 JavaScript:

    var obj = {};
    obj.name = 'test';
    obj.age = 1;
    obj.getName = function() { return this.name; }
    

    你是可以为 obj 注入 getName,并且在下文马上调用它。

    name_of_obj = obj.getName()
    

    “这将允许你进行对象的后天编程,让喜欢抽象的程序员留了一大片自由幻想的天空。”

    ——《谈谈我对 Ruby 的看法》

    文中给了例子,我在这里再贴一遍(单例类):

    class Parent
      def say_hello
        p 'hello'
      end
    end
    
    child_a = Parent.new
    child_a.say_hello // 孩子会父母的说 hello 行为
    
    # 孩子 child_a 后天自己学会说 bye
    def child_a.say_bye
      p 'bye'
    end
    
    child_a.say_bye // 说 bye
    
    child_b = Parent.new // 父母又生了个孩子
    child_b.say_bye // 但是他不会说 bye
    

    我在那篇文章话浅,但指代的含义很深,如果有广泛编程经验的人,他们一定理解我说了什么。

    JavaScript 现在比较火,吾辈看来,也是的得益于它无尽的抽象灵活的能力,它不需要太复杂的 OOP,能够像 lisp 那样轻而易举以 scope 撬动整个抽象出层层叠叠的多次元的世界。

    可参考:为什么说 JavaScript 是披着 C 外衣的 Lisp? https://www.zhihu.com/question/20423080

    很荣幸的是,Ruby 的单例类赋予了开发者这项能力。

    所以,在写 Model 的时候,不用再去担心语言有没有像 ObjC 的 @property 辅助性设施帮你 sythesize getter setter,也不在像 Java 的注解辅助性给开发框架的人对属性 alias 或者别的操作。

    残念,这些一切的一切,Ruby 元编程默秒全~

  • 既然你提到了,我就去看看。

    反正之前我打算用 C + pthread 绕过 GIL,结果失败了,很多 var GC 没有 mark,还有一堆 segment fault。

    后来 @luikore 前辈赐教后,我自己调整了一番,但是还是很多 bug,像 C 作为 IO 主动通知 Ruby 被动接收最好的选择是 mRuby,没那么多折腾。

    总之被 Ruby 的锁折腾得精分,期待 3.0。

  • 我感觉锁的存在让人没办法从 Ruby 级别处理计算密集性能级 IO,只能丢给 C,然后 Ruby 只是在 ready 的时候通知绑定的回调。

  • 没办法,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 得住一个很大的团队。

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

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

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

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

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

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

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

  • Thank you very much!!!

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

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

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

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

  • 姜叔叔都不回我问题,那我自己回答吧,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 或时效(根据配置)有效的。(这讨论的是虚拟机优化部分的内容了)

  • 嗯嗯嗯,好好好,要健康

  • 谈谈我对 Ruby 的看法 at 2017年12月30日

    嗯,我只是抱着【谈谈看法】的态度说出来,分享一下我自己的看法,至于对与不对,我是无辜的。

    就像医学,远古的时候的人类神农,发明些草药,可能只是 “起到某种作用”,但是实际上哪种成分,当时的人类可能是不清楚的,随着尝试药物的人多了,才把药物起的作用分清楚。

    小白鼠,就是科学道路上的牺牲者,没有所谓的天才神啊啥的,都是试出来的。

    对于我在文中对 接口的思想,也是我自己的个人总结笔记,如果大家看了觉得有帮助,那就更好,如果不以为然,有更好的想法,也 Okay。

    如果真的有一位语言学家出现在这里,能说出 xxxx 为什么会这样,因为 xxxx,解谜,这样更好了。

    但是如果只是吹毛求疵,说我是追求装逼什么的,那我下次知道些什么,我宁可不分享,我留着自己用不好?