Ruby Ractor和解释语言中的并行性

Ruby Ractor和解释语言中的并行性 Ractor Ruby 3.0 的主要特性之一是引入了“ractor”。 Ractor 是 Ruby 的一个新的并发抽象。 与 Ruby 线程不同,ractor 可以并行运行。 由于 Ruby 全局虚拟机锁(GVL),即使每个 Ruby 线程都映射到本地线程,也只能有一个活动线程在运行。 但是引入 ractor 后,可以有多个 GVL,每个 ractor 有一个。 这就是 ractor 可以并行执行的原因。 ractor 的引入使 Ruby 能够实现真正的并行性,同时使用一个解释器。 在我们深入研究 ractor 实现之前,我想首先谈谈为什么 Ruby 有 GVL。 Global VM Lock Python 中的 GVL 或 GIL(全局解释器锁)。它是一种解释器范围的锁,可确保在任何给定时间只有一个线程正在执行。它的存在是为了方便解释器的开发。要理解为什么只有解释型语言有这个而其他语言没有,我们需要知道解释器是做什么的。 Ruby 允许动态添加类/模块的实例/类变量,它将这些信息存储在一个表中。现在,如果两个线程正在修改这个表,就会发生数据竞争。解释器所做的另一件事是垃圾收集。关于垃圾收集的信息存储在“对象空间”中,垃圾收集器将遍历这个空间,删除每个未被引用的对象。现在,如果一个线程触发垃圾收集器但另一个线程仍在创建对象,数据竞争也会发生。 所以如果你有GVM,就不用担心上面的问题了。像 Java 这样的语言不允许在运行时修改类变量。而且关于垃圾收集的信息并不存储在一个集中的空间中,它单独存储在每个对象本身上。 在Ractor之前的并发实现 为了实现并行性,Ruby on Rails 产生了几个新的 Ruby 进程。 因为每个 Ruby 进程都有自己的 GVL。 但是我们现在有多个解释器,这使得我们的程序效率低下。 同样,Python 的 Flask 也使用这种方法。 至于 Node.js,它也催生了新的 Js 引擎。 但是 Js 没有 GVL,因为它没有线程。 ...

September 12, 2021

Ruby元编程性能

Ruby元编程性能 2015 年,Pragtob 写了一篇关于 Ruby 元编程的贴子。 好吧,您可能想知道为什么我要谈论五年前写的博客,在一个计算机科学正在以不断加快的速度发展的时代。 我搜索了它,因为在工作中我们遇到了这个问题。 在工作中我们使用 Cocoapods 来进行依赖管理。在 Pod 很少的项目中,您不会注意到 Cocoapods 的速度。但是,假设有 600 多个Pod会是什么样的呢?仅 Cocoapods 生成 XCode 项目文件的时间就可能是半分钟!我们设法将性能问题缩小到 this 非常 Ruby 文件。从表面上看,它是无害的。有一个辅助方法可以使用元编程生成其他方法,省去了手动编写排序结果、记忆等事情的麻烦……但是,也有一些方法仅返回一个常量字符串,但也使用了这个辅助方法。使用 define_method 定义的方法开销很小,但是当该方法被调用数万次时,开销足够大,可以使用一些Monkey Patching来优化它。我修补了那些使用 define_method 但简单地返回一个常量字符串的方法。使用简单的 def 重新定义这些方法导致了 5 秒的优化。 5s 听起来可能不多,但在编程世界中,它就像 3 年! 通常,故事到这里就结束了。但是,我决定深入挖掘。你看,我可以从使用 def 重新定义方法中挤出 5 秒。 Ruby 解释器不能首先做类似的事情吗?我查看了 Ruby 解释器源代码,发现用普通 def 定义的方法和用 define_method 定义的方法确实区别对待。对于def,源代码是这里。 define_method 源代码是 here。主要区别在于def函数的类型是VM_METHOD_TYPE_CFUNC,而define_method的类型是VM_METHOD_TYPE_BMETHOD。不幸的是,我没有发现为什么VM_METHOD_TYPE_CFUNC 比VM_METHOD_TYPE_BMETHOD 快,我也不知道为什么它们是不同的类型。在网上快速搜索也无济于事。所以我只好放弃了这件事。然而,我确实通过这个过程对 Ruby 有了更多的了解。我现在知道默认类是 kernel,你在任何类之外定义的所有东西都会进入内核。而类类型实际上也是……一个类! Ruby 中的符号之所以唯一,是因为 rb_intern 将字符串转换为内部的 ID 类型,相同的字符串转换为相同的 ID。 Ruby 维护一个中央函数表,以确定您正在调用哪个函数、函数可见性和它们所属的类与函数本身一起存储。 测试 好吧,如果您对 Ruby 3.0 中的元编程性能感兴趣,在 Pragtob 的帖子发布 5 年后。 这是测试它的代码。 你需要 benchmark-ips gem 来运行它。 ...

September 5, 2021

下载没看上去这么简单

下载没看上去这么简单 动机 如今,我们实际上并不关心网络下载的内部结构或细节。大多数情况下,我们单击浏览器上的链接并等待进度条完成。 如果我们觉得下载时间太长,通常是以太网速度受到指责。但是,我们从未想过该进度条下方使用的协议。即使对于实际需要实现某种下载代码的程序员,每种语言也总是有高级库。需要HTTPS吗?在您的 URL 前添加 https://,想要多个连接?轻触那个开关,库会为你做所有肮脏的工作。 好吧,直到最近,我也是这些人中的一员。在工作中,我们需要为一个大项目下载数百个依赖项。由于开发速度很快,每个人每天至少需要更新一次。由于依赖项的数量庞大且每个项的发布频率很高,同事抱怨公司聊天室的更新时间过长并不是一个不寻常的景象。我应该调查为什么它需要这么长时间并尝试优化。 现在我们不想更换基础设施,所以如果有的话,所有的优化都会发生在软件方面。使用的下载模式为HTTPS+并行下载。所以通常情况下,我对下载模型性能的不同组合进行了一些测试,我将在下面尝试重新创建。 TCP/IP 模型有四层:链路层、互联网层、传输层和应用层。但是由于我们不希望对基础架构进行任何更改,因此三个低级别层不在考虑范围中。对于应用层,我们可以控制 SSL 和并行/串行下载。 测试环境搭建 对于服务器,我使用我的一台笔记本电脑和 Apache 网络服务器。 首先,我们需要为我们的服务器启用 https。 通常情况下,ssl 证书的价格为数百美元。 但是为了测试,我们将使用自定义的 openssl。 笔记本电脑安装的ArchLinux自带了 openssl。 要生成证书,请运行 openssl req -new -x509 -nodes -out /srv/http/ssl.crt -keyout /srv/http/ssl.key -days 365 是的,我们将密钥和证书都存储在服务器根目录中,但这不是生产环境,只是为了测试。 之后我们将会删除这个目录。 在/etc/httpd/conf/httpd.conf里取消注释这些行之后: LoadModule ssl_module modules/mod_ssl.so LoadModule socache_shmcb_module modules/mod_socache_shmcb.so Include conf/extra/httpd-ssl.conf 在/etc/httpd/conf/extra/httpd-ssl.conf里增加 SSLCertificateFile和SSLCertificateKeyFile的配置, 服务器就已经准备好相应HTTPS和HTTP的请求了。 对于相关的测试文件,我们将使用一些生成的文件。 为了生成这些文件,我编写了这个方便的脚本: #!/bin/bash for ((i=0; i<=$3; i++)) do dd if=/dev/zero of=$1$i.img bs=1024 count=0 seek=$2 done ./dd_create.sh large 10000 100 将会生成100个大小为10000KB的文件,命名为: large1.img, large2.img … 在我运行 ./dd_create.sh small 1 100 和 ./dd_create.sh large 10000 100 后我就有了100个1KB和100个9.8MB的文件,我们可以开始测试了! ...

August 28, 2021

在ArchLinux上使用Btrfs硬盘矩阵

在ArchLinux上使用Btrfs硬盘矩阵 前言 几年来,越来越多的东西占据了我的硬盘空间。 视频,烧录的音乐,离线的ArchLinux镜像源… 只是其中的一小部分。我之前的储存方案是一块128GB的SSD做系统盘,1TB的机械硬盘做储存盘。不过因为那块机械硬盘时间有点久了,感到不是很安全。我加了一块1TB的移动硬盘,和之前的那块组成RAID1的硬盘矩阵。 不久之后,1TB 对我来说已经不够用了。 由于缺少合适的硬盘,我将 2 TB便携式USB硬盘连接到计算机。 并将所有可重新下载的数据移动过去。 游戏、Linux 镜像……就这样使用了3年。 现在,剩下的空间再次处于危险的程度。 留给我的唯一选择是将最少使用的数据传输到我的两台笔记本电脑,每台笔记本电脑都有 500 GB 的空间。 但这显得很不方便和尴尬。 此外,我的家人没有 NAS 或云存储解决方案。 所以是时候进行适当的 Raid 构建了,来存储我自己的所有东西和家庭视频。 基本上把我的电脑变成 NAS。 硬盘 虽然很多人选择像 redwolf 这样的企业级硬盘,我选择了普通的希捷硬盘。 专业 NAS 硬盘的主要优势是高工作负载容量和持久性。 但是,就我而言,我不需要这些。 大部分数据大部分是静态的,没有太多负载。 而对于寿命问题,根据我之前的经验,普通的硬盘就可以了。 此外,我将使用 Raid 10,这意味着我可以在 4 个 HDD 阵列中承受 2 次故障。 最后我选了四个 4TB 的,这将给我在 Raid 10 下的 8TB 存储。 安装 安装本身很简单,拿一把螺丝刀和一些电源线,就装成了。 但是有一个意外的延迟。 我虽然已经检查过我有足够的板载 sata 端口和电源插槽,但是忘了检查机箱是否有足够的槽地方装硬盘。 装了一张盘后,发现硬盘仓用完了! 幸运的是,机箱确实有两个未使用的 CD 驱动器托架,所以我在网上订购了其中一个扩展仓。 带有三个驱动器托架和一个前置风扇,此扩展箱可装入两个 CD 驱动器托架。 我的电脑机箱只有两个驱动器托架,加上这三个,我的硬盘空间刚好够用(4 个新的和 1 个旧的)。 ...

August 22, 2021

Delete the QQmlApplicationEngine?

How I tried to delete QQmlApplicationEngine for less memory usage Qml Qml manages to separate UI and backend logic, one can adjust c++ code without breaking UI, or develop different front end without implementing same logic twice. As plasma mobile developers, we can utilize the flexibility of Qml and Kirigami framework. Making apps that look equally beautiful on mobile and desktop platform. However, the high memory usage is its major drawback. On a device like pinephone which only has 2 Gigs of ram, low memory consumption is crucial. ...

August 31, 2020

Plasmoid with C++

Plasmoid with C++ the screenshot is at the end of this post I’m developing a Plasmoid for Plasma Mobile. Called KClock-Plasmoid, as its name suggests, it’s a plasmoid for KClock. The goal is to display time, next alarm and stay at system top panel to indicate KClock is running in background. KClock side So the goal is pretty simple, and all I have to do is to find a way to share information from KClock to the plasmoid. However the solution isn’t that trivia. As it turned out, DBus is perferred for IPC(Inter-process communication). Before start working on plasmoid, I need to expose some of the class of KClock to DBus first. Since KClock is built upon Qt, I choose to using Q-DBus as it will save a lot of effort than using low level interface. Now the problem is - I don’t know how to use Q-DBus. As usual, I went to the Qt documentation and to my surprise, it spent most content to describe the concept of DBus and compared to Qt’s signal/slot machinism. Although useful as it is, lack of examples meaning I still didn’t know how I can use it in my code. Thankfully, KDE has its own tutorial about DBus and it provides multiple examples. You can find it here. ...

August 12, 2020