Redian新闻
>
一场实验:探索Go程序的进化可能性

一场实验:探索Go程序的进化可能性

公众号新闻

图片由 Waifu Diffusion v1.3(float16)生成,描述为:螃蟹、入侵、海滩、棕榈树、青山地带、吉卜力工作室、异度之刃 2、精灵宝可梦、杉森健、粗线条、水墨风

译者 | 核子可乐 

有时候,我们会想要把别种语言编写的库嵌入到自己的程序里。这类需求在程序员之间早已有之,但出于种种原因,这始终是个充满了危险、恐惧、折磨的艰难过程。

照常来讲,如果想从 Go 中调用 Rust 函数,那我们就必须借助 cgo 这样的跳板。但这样效果不错,而且至少比亲自编写 cgo 这样的工具方便得多。

然而,问题是当我们用 cgo 将 Rust 函数链接到 Go 程序时,还得复制 Rust 生成的共享对象。我们没法把这个共享对象签入源代码树(不同操作系统、不同 CPU 架构的各自系统分发都必须是唯一的,就像常见的动态链接二进制文件一样)。所以虽然有效,但总体来讲其开发者体验很差。这时候就不能简单 go build,还得记得运行 cargo build --release 并确保生成的.so、.dll 或者.dylib 位于操作系统动态链接程序所能读取的正确路径。总之,一团乱麻。

<Mara>这是个大问题,也是 Nix 和 NixOS 存在的原因。想象一下,当我们把通用操作系统组件混入其中,情况会有多么复杂。但令人惊讶的是,这样操作又是真实有效的。那么,如果说有一种方法能让我们从 Rust 发布一个二进制文件,它能在 Go 所支持的任何平台上正常起效;而且只需简单的 go build 就行、不必修改任何构建过程呢?一想就知道能这样可太棒了。对用户来说,他们虽然使用相应的包或程序,却根本感受不到有 Rust 参与其中。我的这个 mastosan 包就是这样的解决方案。下面我想跟大家聊聊它的开发过程以及存在的原因。

为什么要开发 mastosan

Mastodon 的实质就是把素材存储为 HTML 格式,再将该 HTML 呈现了 API 使用者。HTML 特别适合浏览器显示,但对 bot 来说意义不大。所以如果目标是 Slack webhook,那就不太合适。

下面来看 API 中的素材:

其内容如下所示:


理想情况下,我们当然希望它在 Slack 中也有相同的语义,比如像这样:

这条链接在 Slack 中的显示效果跟其他超链接一样。但随着设计复杂度的提升,Mastodon 也会出现某些怪异语义,例如 span 不可见及其他一些烦人的 Slack 显示错误。我们看看以下两条有什么区别:很明显,这两条跟人类正常思维的契合度就不一样。

如何实现

UNIX 理念的核心特征之一,在于将程序视为简单的过滤器。它既能很好地完成一项任务,又允许用户将其组合为新的、更有趣的形式。如果大家曾经把 curl 和 jq 配合起来执行操作,比如从 JSONFeed 中读取数据之类,就能理解这类实践过程:


我用 Rust 编写了一个小程序,它使用 lol_html 来获取传入的 Mastodon 风格 HTML,并发布 Slack 风格的 markdown。用法非常简单:就这么简单。它会接收标准输入并在此之上返回结果。这跟 WebAssembly 流并不直接映射,除非用 WASI 填补其中的空缺。WASI 为 WebAssembly 程序提供了类似于 POSIX 的环境,大多数基础功能都可以直接起效,但这里我们只使用到它的两个主要部分:标准输入和标准输出。


在 Go 中,如果将其作为普通的 OS 子进程运行,可以使用以下代码:

但这仍然要求程序针对本机 OS 和发行版进行编译,而且必须存在于 $PATH 文件夹内。所以有效,但还不够完美。


Rust 允许我们使用以下编译器标记,构建以 WASI 为目标的二进制文件:这会在./target/wasm32-wasi/release/mastosan.wasm 当中生成一个几 MB 大小的二进制文件。只要运行它,就能帮我们达成目标。

现在我们需要在 Go 中用这个二进制文件。可行的办法很多,这里我选择使用 wazero。它的使用流程类似于带 os/exec 的子进程,但也略有不同,因为我们嵌入了 WebAssembly。具体方法如下:

意思基本是一样的:设置环境、加载 WASM 模块,然后运行。主要区别在于,这里我没有把二进制文件作为机器码从磁盘上加载,而是使用 go:embed 将预编译的 WebAssembly 模块嵌入到了二进制文件中。也就是说,只要 WebAssembly 模块的位置符合要求,那生成的 Go 程序就能正常工作。

再快一点

这种实现的主要缺点就是速度略慢。每次调用该函数时,它都必须编译 WebAssembly 模块。

Wazero 运行时和编译后的 WebAssembly 模块代码都可以被举升到包级变量当中,具体如此补丁(https://github.com/Xe/x/commit/b61b59318be6544632ac1f64b1237bb17b2e7a32)所示。这样就能大大改善速度问题。用了这个补丁,WebAssembly 模块只会在应用程序启动时编译一次。在使用此补丁前,每次运行中的调用大概需要 0.2 秒,而使用补丁后的基准测试结果为:

可以看到,最佳用时从 0.2 秒下降到了 0.3 毫秒,意味着性能至少提升了 1000 倍。这意味着大部分时间可能都花在了 HTML 解析器上,而不是无关紧要的其他部分。

我觉得这不仅能满足我个人的工作需求,也应该会帮助更多朋友解决难题。后续我还会用更多随机 Mastodon 消息做实验,看看它能否满足要求。这种将两个不相容的世界融合起来的感受真棒,也期待它能真正在更多实践场景当中发光发热。

原文链接:https://xeiaso.net/blog/carcinization-golang


你也「在看」吗? 👇

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
王希勤 等:探索扎根中国、融通中外的大学人才培养模式 为科教兴国战略提供全方位人才支撑新基因的出现,表明人类的进化仍在继续梅花创投吴世春:新环境下,创业者的进化小透明变身实验大神!吹爆这个保姆级实验protocol!(附13个细胞实验教程)【双养日课 1035】打开记忆的宝藏:探索人生密码《完美食光》:探索红酒背后的破冰故事纽约/法拉盛出发-尼亚加拉瀑布2日游:探索三大州立公园:尼亚加拉瀑布公园+旋涡公园+尼亚加拉古堡公园 NF2搜索GMV增长近400%,这些品牌在抖音电商月入千万观念可能性与实在可能性育儿网CEO程力:如何用一张“网”,助力母婴品牌生意新增长?瞒报涉疫行程被判4年!货车司机申请再审,律师:法院启动再审程序并改判的可能性不大急救队面临的一些问题从操作系统的进化中,读懂MagicOS一个土豪国家的进化之路专访ADI:探索AI MCU应用边界,集成CNN硬件加速器将是边缘AI处理的技术趋势《智本社经济学框架》:探索正确的经济学宏碁新一代笔记本 1 月 4 日发布:探索新平衡从芯片“冷战”,看技术的进化Walker的虚伪和谎言使其遭儿子和女友公开背叛一瞬间,仿佛看到了人类的进化「云集」书影婆娑读书会回归!第24期 :探索社会的进程NeurIPS 2022 | 参数集约型掩码网络:探索有限数量随机数的表征能力秋季鼻血怎么办?夜读咳嗽声识别新冠阳性!这个小程序的产品经理有点意思猴子成功用脑机接口打字要吃的...马斯克想6个月内搞人体实验:我也装一个!新冠特效药火热背后:探索处方药广告合规发展的破局之道中美核心决策程序的根本差异在哪?工农红军与雇佣军的区别在哪里[汽车] 买菜车的进化 Model 3 Performance张朝阳:恐惧和欲望,造就了人类的进化肿瘤自噬、外泌体实验研究,从细胞实验到动物实验,超靠谱的protocol和6位洞见者聊聊天,我们发现了新商业的进化动向25个任务、123次有效载荷、193项实验,Space Tango打造太空实验平台【Space Medicine系列案例】合作共赢:探索大中小企业融通创新模式丨保时捷中国创新加速营融资加速活动
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。