2020年对所有Rubyist来说都是特殊的一年。对不对?Ruby2于2013年发布,我们已经使用Ruby2.x7年了,我们一直在等待Ruby3的发布。终于,等待结束了。我们终于在圣诞节期间获得了Ruby3.0.0,这给了我们有史以来最好的圣诞礼物,为这种高级通用编程语言带来了更高的性能和其他功能。是时候打开礼盒并查看我们获得的所有Ruby3功能了。Ruby3.0的开发着眼于更高的性能、并发性和类型,并成功实现了比Ruby2.0性能快3.0倍的目标。使用新的Ruby3.0的即时(JIT)运行时编译器时实现了3.0倍的加速,但就其VM实现而言,与Ruby2相比仍然是一个相当大的加速。可能有人会问,为什么Ruby3.0的性能提速与Ruby2.0相比,而不是Ruby2.7呢?请到官网阅读releasenotes,2015年目标是性能提升3倍。Ruby3.0的JIT表现出了非常好的性能,非常适合需要多次调用多种方法的工作负载。Ruby3.1承诺为需要更多方法调用的工作负载提高JIT性能。Ruby3.0还提供了一个实验性的“Ractor”,用于并行执行能力而不用担心线程安全;FiberScheduler允许拦截阻塞操作、改进静态分析、改进单行模式匹配以及许多其他更改。Ruby3主要更新数字3在Ruby3版本中意义重大。它是将性能提高3倍的发布版本号,核心贡献者(Matz、TenderLove和Koichi)也是三人组。同样,Ruby3有3个主要目标:更快、更好的并发性和正确性。1.Ruby3性能性能是Ruby3的主要关注点之一。事实上,Ruby3从一开始就在开发团队内部进行了讨论。Ruby创始人Matz(YukhiroMatsumoto)在2015年设定了一个雄心勃勃的目标,将Ruby的速度提高三倍。什么是Ruby3x3?在讨论这个之前,让我们重温一下Ruby的核心理念。“我希望看到Ruby帮助世界上的每一位程序员提高工作效率,享受编程的乐趣,”Matz说。”关于Ruby3x3,有人问目标是不是让Ruby成为最快的语言?答案是否定的。Ruby3x3的主要目标是让Ruby比Ruby2快3倍。Matz说:“没有语言足够快。“Ruby并不是为了最快而设计的,如果那是目标,那么Ruby就不会成为今天的样子。随着Ruby语言性能的提高,它肯定会帮助我们的应用程序变得更快和更具可扩展性。Matz承认:“在设计Ruby语言时,我们主要关注生产力和编程乐趣。结果,Ruby太慢了。“有两个方面可以衡量性能:内存和CPU。CPU优化Ruby中进行了多项增强以提高速度。Ruby团队从以前的版本中优化了JIT(JustInTime)编译器。RubyMJIT编译器是最早在Ruby2.6引入。Ruby3MJIT有更好的安全性,似乎在很大程度上提高了web应用程序的性能。MJIT的实现不同于通常的JIT。当方法被重复调用时(比如10000次),MJIT将选择可以编译为本机代码的方法并将它们放入队列。稍后MJIT将获取队列并将其转换为本机代码。内存优化的Ruby3带有增强的垃圾收集器。它的API具有类似python的缓冲区,这有助于更好地利用内存。从Ruby1.8开始,Ruby在垃圾收集算法方面不断进步。自动垃圾压缩垃圾收集的最新变化是垃圾压缩。它在Ruby2.7引入,过程有点手动。但在版本3中,它是完全自动的,适当地调用压缩器以确保适当的内存利用。对象分组垃圾压缩器移动堆中的对象。它将分散的对象分组2.Ruby3中的并行性和并发性并发性是任何编程语言的重要关注点之一。Matz认为Ruby程序员还没有正确使用线程的抽象层。Matz说:“我对添加线程感到遗憾。”Ruby3使并发运行应用程序变得更加容易。Ruby3中添加了几个与并发相关的特性和改进。纤程在Ruby3中,纤程的引入被认为是开创性的。Fibers是轻量级的工作线程,看起来像线程但有一些优点。它比线程消耗更少的内存。它使程序员可以更好地控制定义可以暂停或恢复的代码段,从而实现更好的I/O处理。FiberSchedulerFiberScheduler是Ruby3中加入的一个实验性特性,引入它是为了拦截I/O等阻塞操作。令人高兴的是,它允许轻量级并发,并且可以轻松集成到现有代码库中,而无需更改原始代码逻辑。这是一个接口,可以通过为EventMachine或Async等gem创建包装器来引入。这种接口设计允许分离事件循环实现和应用程序代码之间的关注点。以下是使用Async并发发送多个请求的HTTP示例。require'async'require'net/http'require'uri'LINKS=['https://xmyy.com','https://www.xmyy.com']AsyncdoLINKS.eachdo|link|AsyncdoNet::HTTP。get(URI(link))endendendRactors(Guilds)众所周知,Ruby的globalVM锁(GVL)可以防止大多数Ruby线程并行计算。Ractor可以解决这个问题,而GVL可以提供更好的并行性。Ractor是一种类似于Actor-Model的并发抽象,旨在提供并行执行而无需担心线程安全。Ractors允许不同Ractors中的线程并发计算。每个Ractor至少有一个线程,线程可以包含多个Fibers。在Ractor中,在给定时间只允许一个线程执行。以下程序返回一个非常大的平方根。它并行计算两个数字的结果。#Math.sqrt(number)inractor1,ractor2runinparallelractor1,ractor2=*(1..2).mapdoRactor.newdonnumber=Ractor.recvMath.sqrt(number)endend#sendparametersractor1.send3**71ractor2.send4**51practor1.take#=>8.665717809264115e+16practor2.take#=>2.251799813685248e+153。静态分析我们需要进行测试来保证我们程序的正确性。然而,就其本质而言,测试可能意味着重复代码工作。Matz甚至抱怨道:“我讨厌测试,因为它不是由人来完成的。”为了保证程序的正确性,除了测试之外,静态分析也是一个很好的工具。静态分析依赖于内联类型注释。解决这个难题的方法是使.rbs文件与我们的.rb文件平行。RBSRBS是一种用于描述Ruby程序结构的语言。它为我们提供了程序的概述,以及如何定义整个类、方法等。使用RBS,我们可以编写Ruby类、模块、方法、实例变量、变量类型和继承的定义。它支持Ruby代码中的常见模式以及联合和鸭子类型等高级类型。这些.rbs文件类似于TypeScript中的.d.ts文件。下面是一个.rbs文件可能是什么样子的小例子。具有类型定义的优点是可以根据实现和执行对其进行验证。下面的例子是不言自明的。我们在这里需要注意的一件事是each_post接受一个块或返回一个枚举器。#user.rbsclassUserattr_readername:Stringattr_readeremail:Stringattr_readerage:Integerattr_readerposts:Array[Post]definitialize:(name:String,email:String,age:Integer)->voiddefeach_post:(){(Post)->void}->void|()->Enumerator[Post,void]end其他值得注意的更改可以更快地粘贴到IRB中。回溯的顺序被颠倒了。首先打印错误消息和行号,然后是其余的跟踪信息。Hash#transform_keys接受将旧密钥映射到新密钥的哈希。使用#frozen-string-literal:true时,内插字符串文字不再冻结。Symbol#to_proc现在返回一个lambdaProc。添加了Symbol#name,它以冻结字符串的形式返回交易品种的名称。过渡许多核心库已被修改以满足Ruby3目标要求。但这并不意味着我们的旧应用程序会突然停止工作。Ruby团队已确保这些更改向后兼容。我们可能会在现有代码中看到一些弃用警告。开发人员可以修复这些警告,以便从旧版本平稳过渡到新版本。我们都准备好使用新功能,并希望从新的性能改进中受益。结论随着性能、内存利用率、静态分析以及Ractors和Scheduler等新特性的巨大改进,我们对Ruby的未来充满信心。使用Ruby3,应用程序的可扩展性和易用性会大大提高。即将到来的2021年对于所有Rubyist来说不仅是新的一年,更是一个新的时代。
