为啥 Erlang 没有像 Go、Scala 语言那样崛起?

news2024/9/25 5:23:55

为啥 Erlang 没有像 Go、Scala 语言那样崛起? - 知乎

问:

成熟的杀手级产品,技术栈完整,社区活跃,易上手使用的人比较多。
scala 目前业界应用广泛,技术栈完整,社区活跃,还有 spark 这个重量级杀手锏;go 类似,也有 docker;erlang 呢?为什么没流行起来?从语言特性,成本,生态圈,推广代价等分析讨论。

Worse is Better (

http://dreamsongs.com/RiseOfWorseIsBetter.html

)能比较好地解释题主的「为什么」。注意这篇文章的写作背景,这是一位 LISP 大佬在九十年代初反思为什么 LISP 这么牛的语言日渐式微,C 和 UNIX 这么烂的东西却起来了。概括下来大概是这样的:

软件设计有以下四大目标:简单、正确、一致、完整,但两大流派 MIT Style (MIT AI Lab 是 LISP 重镇) 和 New Jersey Style (C 和 UNIX 的老家贝尔实验室所在地) 对这些目标的优先级排序不同。MIT Style 认为软件正确性要绝对保证,然后优先级 正确 ~= 一致 > 完整 > 简单,简单这一条还得分,为了接口简单,可以忍受实现复杂。而 New Jersey Style 是正好反过来:首先软件实现得简单,做不到宁愿让接口复杂点,为了简单显然可以牺牲完整性,而正确、一致,那就尽力吧…… 反正得简单。Worse is Better 前面的 Worse 指的就是像 UNIX 这样为简单甚至能放弃「正确」这种有绝对标准的好的东西,后面的 Better, 指的是更好的生存适应性,这里面不带价值判断,文章作者也为 "Worse Is Better Is Worse" or "Worse is Better is Still Better" 一直在纠结,但这是一个能解释很多现象的准确观察。

没错,Erlang 就是 MIT Style, do the right thing 那个。它跟 LISP 一样产生深远的影响,会被无数后世语言技术借鉴 —— 即使不用 Erlang 开发我还是会对每个新人都会高度推荐 Erlang paper (

http://erlang.org/download/armstrong_thesis_2003.pdf

) —— 可是能火起来的,还会是那帮新泽西佬做出来的敢连 generics 都没有的烂货。

一个东西火起来的关键在于传播。文章把 C 和 UNIX 比作病毒:它实现(而不是接口)很简单,所以能很容易移植(感染)到别的平台,迅速跟原有平台的东西整合,因为它东西少,不拘泥于「正确」、「本质」之类的东西,能根据平台和需求快速演化,也能不断吸(chao)收(xi) 别人的东西让自己变得更强大。

但是 Erlang 不行,阻碍 Erlang 传播的除了爱立信作死,还有它自己的特性。A History of Erlang 里数次提到,Erlang 很难移植到别的语言/运行平台,因为 Erlang 的运行模型太特别了(真可惜只有Erlang是对的),所以一切都只能自己搞,同样原因要调用宿主平台的原有模块也很困难。Erlang 有一个简单、正确、不妥协的接口,但是底层实现就不得不非常复杂精巧,当底层实现的优化都不能满足你的特定需求时,你很难绕过统一美好的模型做case by case, quick and dirty的优化。某个算法 Erlang 跑太慢了你要引入 C 模块,难(望向 PHP & Python),复制消息传递通常不是瓶颈但如果变成瓶颈能传指针么?NO, YOU'RE DOING IT WRONG! 当然实际上 Erlang 内部对这个是有优化的,大的 binary 会自动变一个引用计数 buffer 放共享堆然后就只用传引用啦,但是这马上导致一个问题,因为 Erlang 没有(不需要有)全局 GC, 如果有进程已经不引用这个 binary, 但因为各种原因触发 GC 迟了,共享 heap 里引用计数一直不清零这段 binary 就僵在那流量冲击大你就等OOM吧,这是实际线上系统会碰到的问题,Binary是不是refc又不是你说了算,所以还是时不时自己强行 GC 一下…… 这其实就是一个接口简单导致实现复杂优化困难并且难以做对结果还是要用户自己动手的例子。Go 的 STW GC 虽然简陋,但它不限模型,鼓励复制但不禁止传指针,对这种少数的 case 很容易解决,再拿个 pool 来对付一下蠢萌的 GC 就可以了。模型不纯粹,实现极简陋,但解决问题。

Worse is Better 也能解释别的语言或技术的崛起。你不用很优秀但要有一个点做得好打到痛点,你不用设计完美但至少别犯大错,然后保持简单,保证好上手易移植易与现有系统整合,就可以了。包括 PHP(别打我),它架构上首先基于 CGI: 每个请求一个独立进程,share nothing,只用管道跟 httpd 通信,这天然保证错误隔离,也让 CGI 应用完全不需要管网络交互问题,短连接模型处理完请求就进程结束所以 PHP 甚至不需要 GC, memory pool 就行,更重要的是它也天然支持了热替换。你可以说这些全部是 Erlang 的设计点,也完全符合 Erlang paper 提倡的把困难问题(HTTP server)做成框架让业务写得简单轻松的思路,同时这也是传统的 UNIX 编程方式 —— 这就是所谓设计上别犯大错。然后再做一个亮点:直接 HTML 代码里嵌入脚本,现在你觉得这很傻,但当时互联网刚起来,HTML 还是新鲜事物,更没有什么 AJAX, 不用你自己组装字符串直接把代码嵌到 HTML 里太打动人心了。是,这没什么难的,但别人没有,PHP 有。至于一台机撑多少连接?速度怎么样?当时有个人访问你网页你都兴奋半天了,谁跟你研究这种吃撑了怎么办的问题?

如果 Worse is Better 作为一个定律是正确的,这听起来很可悲,我们就活该没有好东西用了。我感觉可以稍微修正一下:对于开发技术这种存在网络效应的东西,除非一个方案有革命性的优势,否则都会服从 worse is better 定律。

在电信行业,Erlang 可能真的拥有革命性的优势,我不熟悉的领域不评论,可惜电信行业本身相对狭窄封闭再加上爱立信作死,没网络效应可言。而在其他地方,革命性的优势,它没有。

开发效率方面

@bhuztez

提到的好 8 倍,我记忆中来自 A History of Erlang 描述一个早期项目,对比对象是一个没什么公开信息的内部语言 PLEX,而且 Joe 说了原始文件从未公开,且当时内部争议就很大;Erlang 标志性项目 AXD 301 的报告结论 (

http://www.erlang.se/publications/Ulf_Wiger.pdf

) 是 4 倍,对比对象是 C/C++,方法是对比代码长度(所有动态脚本语言都能赢好吗)和bug密度(相同),更重要的是,它并没有分析 Erlang 的语言特性在开发效率提高中的必然作用,甚至没有代码对比样例(报告里倒是有一堆组织架构管理方法内容),也没说明有 C++ 使用什么能跟 OTP 对应的框架,这种论据拿到知乎上是会被喷死的。

运行时方面

Erlang 的高并发只能说它是生不逢时。90年代,除了电信领域,这种高并发需求实在没有,要真有,QQ算?人家用 UDP 木有连接保持问题。当时的硬件情况,机械硬盘、网络带宽、CPU 内存逐个撑死了都还没轮到并发。Telnet-based BBS 是 TCP 长链接模型,用最基本的 UNIX fork 进程模型(操作系统级进程隔离,要不是这样那十几二十万行sh*t还真跑不起来),中山大学逸仙时空用一台 98 年的 HP Alpha(以前的DEC)机器 2G 内存好像?能撑 3000 在线,水木PTT等大站有好硬盘好CPU 4G乃至8G内存20000在线不在话下,注意是在线,发呆会被踢的,所以这些连接的活动率很高(作为对比 AXD 301 用的是 Sparc Ultra 2 跑 Solaris 活跃进程有200-4000)。系统的瓶颈一是硬盘二是内存,远远没轮到模型问题。到编程模型真有问题的时候,Worse is Better 已经发挥作用,各种现有开发平台借鉴 Erlang 模型可以搞出很好的东西 —— 为什么是借鉴而不是直接用 Erlang? 答案 Joe 自己已经说了,他在 erlang paper 里鼓励separate of concern, 框架模型这么复杂的东西应该由专业人士一次过搞定,模型之上的应用就很轻松而且根本不用关注并发问题;在 A History of Erlang 中,他提到一个想法,Erlang 是一个运行平台,进程里跑的是什么语言并没有太大关系。那也就是说,虽然用别的语言山寨一个并发运行环境很难(而且很难做对),但是这只是一个一次性的工作而且可以根据业务特性定制,框架完成后,你还是可以用熟悉的语言写业务,完全不用管并发问题,但同样能达到好很多的并行度(所谓Actor / Reactor模型blah blah blah, 或者像MapReduce这种特定框架),而且只需要对少数关键模块动手而不是全局替换,性价比高很多吧。

分布式方面

分布式支持的故事也一样,Erlang 从原理上天然支持分布式,也很早就有了内置分布式支持。然而,这个支持所基于的假设也一样老:几个到十几个节点,均质且可靠全互联的网络,单一的全 Erlang 系统。Joe 怎么也不会想到有人要用几万台破 PC 做集群还妄想跨洲跨机房热备。到我们真的需要分布处理能力的时候,你会发现实现的设计假设限制了它的扩展性(

http://release-project.softlab.ntua.gr/documents/ifl12.pdf

),CAP 的基本限制在,不可能有一致、透明的分布式通信和状态管理方案(

[erlang-questions] State Management Problem

这个 thread 可以看到最后 Robert Virding 的总结陈词),你还得去连不按 Erlang 规则来的别的服务,你也没法把 mnesia 扩展到 GFS 的规模,因为它根本不是为这个设计的,Erlang 的这些先发优势没有变成劣势已经很不错了。现在回去看 GFS 和 MapReduce 的论文,你会觉得他们简陋得可笑,里面大篇幅的 fault tolerence 的东西,都是 Erlang 设计原则的特化和简化,可是至少在那时,Erlang 没有发挥它的威力,而 New Jersey guys 蛮干硬上把东西做出来了。你甚至可以认为整个 Google 集群管理系统 Borg 就是一个大号 Erlang 平台,一堆 supervisor 在管着一堆 share nothing RPC 消息通信随时会挂的服务(流行用语叫 micro service),绝大部分服务无状态可以随时挂,Goolge C++ 不允许抛异常但是规定你如果发现完全没预料到的东西你应该直接打log crash掉等重启处理,自动均衡部署容灾一应俱全,几乎无限扩展,处处闪耀着 Erlang 的思想光芒,但它们都是用 C++ 写的。开源版 Kubernets 就是 Go 了,Go 没有内置分布式支持,因为整个体系在,它自己已经不需要了。

这完全就是 Worse is Better 的原文:“The good news is that in 1995 we will have a good operating system and programming language; the bad news is that they will be Unix and C++.”

Google Trends, 全球数据,erlang vs. golang

最后还是多嘴一句,这不是说我们就不应该用 Erlang. Paul Graham 在

Beating the Averages

里提到,Common Lisp 是他当年创业的秘密武器,让他们获得了比用 C++ 或 Java 的竞争对手高的多的开发效率。没人用又怎样?你就是要用普通人不用的东西才能战胜普通人。同样的,如果你相信 Erlang 是你能打败庸众的秘密武器,Go for it (pun NOT intended).


作者:布丁
链接:https://www.zhihu.com/question/38032439/answer/84176970
 

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

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

相关文章

Bun v1.0.3 发布,Zig 编写的 JavaScript 运行时

导读Bun 发布了其最新版本 v1.0.3,这是一个集 JavaScript 运行时、打包器、转译器和包管理器于一体的工具。这次的更新不仅修复了众多已知的问题,还引入了一系列令人期待的新功能。 首先,Bun 在这个版本中增加了对 TypeScript 的 emitDecora…

C++ 重载运算符在HotSpot VM中的应用

C支持运算符重载,对于Java开发者来说,这个可能比较陌生一些,因为Java不支持运算符重载。运算符重载本质上来说就是函数重载。下面介绍一下HotSpot VM中的运算符重载。 1、内存分配与释放 在C中可以通过new运算符创建一个C的类实例&#xff…

整车热管理「升温」,哪些厂商排名电子风扇市场份额TOP10

作为整车热管理系统的关键组成部分,风扇在传统燃油车时代主要是帮助发动机、空调系统进行散热冷却;同时,产品也经历了从硅油风扇到电子风扇(从有刷电机到无刷电机的演进)的升级。 而在新能源汽车的架构中,…

安防监控视频汇聚平台EasyCVR视频广场搜索异常,报错“通道未开启”的问题排查与解决

安防视频监控系统EasyCVR视频汇聚平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTMP、FLV、…

arcgis添加天地图山东wtms服务

arcgis添加天地图wtms服务 首先打开天地图山东网站,进入首页![天地图山东首页](https://img-blog.csdnimg.cn/89df69e1c3d645b4a9e9652a08580342.png)然后点击开发资源进入开发页面点击成为开发者,进入申请秘钥页面,申请秘钥;![在…

Axure常用技巧及问题

以下内容将持续更新 目录 一、技巧1、版本选择2、快捷键3、定制工具栏 二、问题1、无法在浏览器预览2、发布到本地的HTML无法查看 一、技巧 1、版本选择 2、快捷键 3、定制工具栏 上方菜单栏-右键-自定义工具栏 二、问题 1、无法在浏览器预览 需要更改Axure配置 点击发布-…

win11无法打开chm格式的文件

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

NPM 常用命令(十一)

目录 1、npm shrinkwrap 1.1 使用语法 1.2 描述 2、npm star 2.1 使用语法 2.1 描述 3、npm stars 3.1 使用语法 3.2 描述 4、npm start 4.1 使用语法 4.2 描述 5、npm stop 5.1 使用语法 5.2 描述 6、npm team 6.1 使用语法 6.2 描述 6.3 详情 7、npm test…

MES系统电子秤数据采集

一、MES系统电子秤数据采集的意义: 电子秤数据采集是指利用电子秤设备对生产过程中的物料重量进行实时监测和记录。MES系统电子秤数据采集的意义在于提供一个集中管理和监控生产过程中物料重量的工具,使企业能够实现以下目标: 1. 质量控制&…

(部署服务器系列一)虚拟机模拟部署服务器

1、下载安装vmware 15 (win7最高支持版) 2、下载安装CentOS 配置2核2g(最少)磁盘100g(不会实际占有)选择时区-上海配置分区:https://blog.csdn.net/qq_35363507/article/details/127390889 &a…

GPU 虚拟化技术MIG简介和安装使用教程

使用多实例GPU (MIG/Multi-Instance GPU)可以将强大的显卡分成更小的部分,每个部分都有自己的工作,这样单张显卡可以同时运行不同的任务。本文将对其进行简单介绍并且提供安装和使用的示例。 什么是MIG NVIDIA Multi-Instance GPU (MIG) 技术是 NVIDIA…

Java 获取服务器资源(内存、负载、磁盘容量)

1.说明 我们经常通过SSH终端发送shell命令进行服务器运维,从而获取到服务器的各种资源,按照这个思路,我们可以利用Java做一个定时任务,定时采集服务器资源使用情况,从而实现服务器资源的动态呈现。 2.封装SSH操作方法…

淘宝商品详情API接口(item_get-获得taobao商品详情接口),淘宝API接口

淘宝商品详情API接口(item_get-获得taobao商品详情接口),淘宝API接口可获取到商品链接,商品ID,商品标题,商品价格,品牌名称,店铺昵称,sku规格,sku属性&#x…

RK3568平台开发系列讲解(驱动篇)RK3568 PWM的使能与使用

🚀返回专栏总目录 文章目录 一、修改设备树1.1、添加 GPIO3_C5 引脚信息1.2、向 pwm15 节点追加信息二、使能 PWM 驱动三、PWM 驱动测试3.1. 确定 PWM15 对应的 pwmchipX 文件3.2. 调出 pwmchip15 的 pwm0 子目录3.3. 设置 PWM 的频率3.4. 设置 PWM 的占空比3.5. 设置 PWM 极…

Mysql8.0~gh-ost~default_authentication_plugin导致ddl卡住

一、引言 最近线上有个表要加几个字段,提交db单之后执行了一天都没有结束,这个表的容量不大不应该这样。因此作者与DBA进行了深入沟通,了解了集团使用gh-ost更新表结构的过程,问题出在交换表名的过程中。 二、分析 看的ddl单据卡…

使用零宽字符,隐藏信息(加密、解密)

零宽字符就是零宽度字符是一种不可见,不可打印的字符。它们主要用于调整字符的显示格式。 常见的零宽字符有: 使用零宽字符给信息加密: 通过零宽字符来加密文本,我们需要先将文本转成二进制的形式即只包含0和1,并使用…

设计模式 - 备忘录模式

目录 一. 前言 二. 实现 三. 优缺点 一. 前言 备忘录模式又称快照模式,是一种行为型设计模式。它可以在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态,以便在需要的时候恢复到原先保存的状态。在不违反封装的情况…

Python数据攻略-递归方式实现json多层级数据展平

之前介绍过使用pandas如何展平json的多层数据,如果有兴趣可以参考文章 Python数据攻略-Pandas的json_normalize方法 Python数据攻略-递归方式实现json多层级数据展平 今天再介绍一个非常好用的使用递归的方式展平json数据。 文章目录 数据处理目标操作示例核心函数方法操作…

【力扣每日一题】2023.10.11 奖励最顶尖的k名学生

目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们两个字符串数组,分别表示正面评价的单词和负面评价的单词。再给我们n个学生的评语,评语中有一个正面单…

利用无线通信技术搭建蒸汽流量远程监测系统

一、应用背景 2021年国务院政府工作报告中指出,扎实做好碳达峰、碳中和各项工作,制定2030年前碳排放达峰行动方案,优化产业结构和能源结构,特别是近期煤炭价格上涨导致蒸汽价格大幅上涨,节能减排显得更加重要&#xf…