当前位置:   article > 正文

世界的本质就是Unsafe,美好需要我们共同创造

unsafe rust可以学吗

Article Source: https://zhuanlan.zhihu.com/p/103353305

Author: 张汉东

我本来做actix是因为有趣,想去创造,想要尝试Rust的潜能极限。
但现在我为什么这么不开心呢,生活本该不必如此。
再见了,各位。  ————总结自 Actix 作者Nikolay Kim(又名 fafhrd91 )的文章

Actix-web的作者宣布退出开源界,想要正确看待这件事,你首先需要理解Actix作者的初衷。(本文结尾也附上了那篇文章的翻译。)

前因后果

自从Actix问世以来,挺受欢迎,毕竟,Rust的Web框架不是很多。

在性能上屡屡罢榜 techempower 的性能测试榜单。

也不知道从何时起,Actix中使用Unsafe的情况被大家挖掘了出来。

最开始是Nikolay做出了积极的改变,我在做Rust日报的时候,清楚地记得,他看到反馈接下来的几天,积极地宣布自己改善了多少Unsafe的问题,剩下多少问题,是为了什么目的。

然后事情就这么安静地过去了,空气中传来了快乐的气息。

但现在回想,也许他当初积极的态度,为今天的事情埋下了伏笔。

也忘记了过了多久,有人继续在找Unsafe的问题,也不管Unsafe代码到底会不会产生UB或Bug,但凡看见Unsafe可能就很敏感。就像是Unsafe PTSD患者。

对于这些情况,Nikolay选择了无视。这正好和他最初积极响应修改Unsafe的态度相反,所以刺激了某些人,在Reddit上面发出了声讨贴,于是,大家提到Actix,提到Actix的作者就有了下面的标签:

  • 性能测试作弊者。

  • 强行写Unsafe,别人提了意见也不去修改,自以为是。

我相信,如果换成任何人,心里都不会舒服。

Nikolay并没有义务给大家科普Unsafe Rust到底该如何使用。

但他的表现真的是那样吗?

当然不是,对于一些合适的PR,他是Merge了的。但是对于每个PR,他也会如是拷问。是真的解决问题了吗?

这是前因。

直到昨天,Nikolay收到一个issues,这个issues虽然被删了,但是据说在里面骂了Nikolay,而Nikolay还在思考如何解决Actix-web中的问题。

然后Nikolay 生气了,就把actix-web的库迁移到了自己私人仓库里。

我的看法:

很多人说 Nikolay 有点小气。但我不这么认为,去看看上面前因后果,换了谁也不忍受不了。

我从Actix 0.7开始关注并使用Actix做项目,直到Actix-web 1.0。

你们可以对比下 actix-web 0.7和1.0 的重构变化,你会看得出来Nikolay是多么用心在做这个项目。

他是带着自己的创意,想去完成一件作品,是想突破自己,也想看看Rust的潜能极限在哪里。结果被人打上「性能测试作弊者」的旗号,可悲不可悲?

来自官方和社区的声援:

Thank you for your service :github.com/actix/actix-

A sad day for Rust:words.steveklabnik.com/

Actix 支持者之信:github.com/actix-suppor

矛盾的根源

其实,这件事的矛盾本质是大众对Rust的Unsafe不太理解造成的。我当时在写《Rust编程之道》的时候,最后一章标题是《不安全的Rust》,但是编辑看到这章标题跟我反馈,「Rust不是号称安全吗?为什么这里是不安全的Rust?」,于是我意识到问题所在,改成了「超越Rust的安全边界」。

我其实就是想表明,Unsafe Rust,是Rust的安全边界。世界的本质就是Unsafe的。你无法避免它。

还有人说,因为Unsafe Rust的存在,所以也不见得能比C/C++安全到哪里去?

Unsafe Rust确实和C/C++一样,要靠人来保证它的安全。但它对人的要求更高。

它也给了开发者一个Unsafe的边界,这其实也是一种安全边界。它把你代码里的雷区,显式地标记了出来。团队代码里review的话,可以更快地发现问题。这本身就是一种安全。

而反观C++,每一行代码都是不安全的。

以下是我总结的五条使用Unsafe的简单规范,方便大家做权衡:

1. 能用Safe Rust就用Safe Rust;
2. 为了性能可以使用Unsafe Rust;
3. 在使用Unsafe Rust的时候确保不要产生UB,并且尽量判断其安全边界,抽象为Safe方法;
4. 如果无法抽象为Safe,需要标注为Unsafe,并配以产生UB的条件文档;
5. 对于Unsafe的代码,大家可以重点review。

针对这件事,Rust 核心团队Unsafe内存安全模型的负责人RaphJ也专门写了篇文章:

我给大家做了一个摘录,详细的去看原文:raphlinus.github.io/rus

《关于「可靠/安全」的承诺 (The Soundness Pledge)》

Unsafe 关键字具有特定的含义:这表明需要更多的推理才能证明使用代码是安全的。

在 Unsafe 块之外,编译器实质上使用在类型系统中编码的信息来证明使用代码是安全的。在Unsafe块中,会允许某些通常被禁止的事情,例如读取和写入原始指针。

对于不太了解Rust的人,建议阅读Rust书中的Unsafe Rust一章。否则,很多讨论可能会造成混乱。

在Rust社区的某些地方,人们倾向于认为Unsafe本身是很糟糕的,但是我认为这有一些微妙之处。当然,用安全的Rust可以很容易地编写代码,使用Unsafe的方法获得一些可察觉的性能提升。但更糟的是,通过借用检查器来减少抱怨,这不是一个最佳实践。

然而,对于许多用途,尤其是与为其他语言设计的库或运行时集成,这是必不可少的,并且良好地使用它很重要。其他有效的用例包括SIMD和基础数据结构的实现;Rust标准库具有良好的集合,但并不旨在全面涵盖所有可能的用例。

有时,避免安全性错误(UB)相当容易:只需在代码中的任何地方都不要使用“Unsafe”,并且不要依赖任何其他有安全性错误的库。对于某些类别的问题,这是可行的。通常,它是在性能和安全性之间进行权衡的,但是我还没有看到很多证据表明这确实是一种权衡。

在大多数情况下,Rust为您提供了实现这两种功能的工具,但是有时确实需要额外的工作。Rust中的许多安全保证都是零成本的。其他一些方法(尤其是数组边界检查)需要一定的成本,但是即使在安全范围内,普通的性能调整技术也通常很有效。对此的一个数据证据是pulldown-cmark,它现在具有同类最佳的性能,但不使用不安全的方法(存在可选的SIMD优化,但是性能与默认配置几乎没有不同,这要归功于通过 Marcus Klaas de Vries)。

这篇文章很长,并且后面还列举了使用Rust和其他语言、库打交道过程中使用Unsafe的一些问题和看法,欢迎大家去仔细阅读,有欢迎翻译分享。

总的来说,我们应该建立对 Unsafe的正确认知:「Unsafe Rust是一个锋利的工具」。

对待Unsafe的态度是:

1. 对于那些知道如何正确使用Unsafe来完成目标的人,报以尊重。

2. 不要滥用Unsafe。

Rust库的可靠性承诺

为了避免出现同类的事件,RaphJ在上面的文章中还提出了一个建议:

就是在每个crate或框架中,引入这样的一句话:

「“这个crate的目的是为了消除缺陷。开发人员将尽最大努力避免它们,并欢迎在分析和修复它们方面提供帮助。”」

加这样一句话的原因在文章里有阐述:

虽然几乎每个人都同意可靠比不可靠要好,但是 不同的人对它的重要性有不同的优先级,特别是在编码工作和性能之间的权衡。大多数Rust开发者群体高度重视可靠性,但即使在其内部也存在显著的变异。我已经提出了一个承诺,一个真正的意向声明,我希望可以用来清楚地传达Rust工程的优先级别。现在,我是在邀请讨论,而不是提议把它作为一个正式的标志。

正是因为每个人对安全和性能的期望有所不同,所以最好在自己的框架或crate里加上,你们侧重的是哪一点?这样使用者自己可以判断。

Actix作者最后的发言文章

翻译(来自于Rust中文社区Jim,请大家不要在评论此文翻译的如何,不是重点):

Actix-Web 的遗嘱:

有一天,又一个该屎的unsafe风波,我已经麻木了。

真的很有意思,断章取意的读评论会如此容易,(尤其是母语非英语的)写有边有檐的评论的这么难。怎么打补丁?很容易吧,直接,简单,一点都不用创意,一点也不改多余的代码,目的就是把unsafe 去掉,多余的什么去根本的都不用多想哈。我认为软件编程是一个世界上数一数二,最需要创意的工作,创意是人们爱软件编程的源泉。特别是做一个实际的,世界人都能用的项目,这样的实际项目都有条条框框,需要创意才能满足的需求。这样的项目才有意思。一直在你挑战你能力的极限很有意思。没有创意的修改方式很没有意思,(哦,那个作者终于不要这个补丁的版权了(好讽刺啊))。我从来不是一个随便用unsafe的人。我用它是因为我相信我的用法是unsafe但不影响我的安全性。不会有被黑的漏洞。我相信这个问题的确属于mutable aliasing invariant, 我也很高兴有人找出来一个真正需要解决的问题。我也希望解决这个问题,只是不是这样没有创意的解决办法。实在不行在用RefCell来解决。比如我找到了一个我认可的解决方案,现在在master里,至少解决那个issue里面提到的一个题。你们真的太过分了 。

维护大型开源项目一点也不好玩。总有人没礼貌,传播恨,大家都知道怎么写软件,却没有人愿意仔细做功课,读官方文档,想一想,更没有人愿意做贡献。看来大家都以为我们actix团队超级打,每天无所事事,经费更是张口就来。(在这里仍要感谢这写默默支持我们的人)。比如 async await花了三周一天十二个小时,很累人的,发不后又有人抱怨文档没更新,我又要更新。真是令人身心鼓舞啊!你们发现这个该屎的unsafe风波后。我在社区出现的时间
越来越少。真的,这么努力的你看到如此不体贴的评论真的感觉自己被背叛了我也知道删issue
是个挺二的主意,但是做后两个针对我的评论真是气不打一处来。特别是我看到这评论前我还在想解决方案。我不该。

我写actix有三年了。我学到了很多,见到了好多新人,我找到了我心爱的语言,我想一辈子用。我找到了有意思的工作。但是损我项目的名声真是够了。我不认为我身心可以恢复了。我想Actix永远都是别人眼里的“无名小婊渣”,“目标骗子” (我设远大的目标是因为我想把rust的潜力都用出来,我争强好胜,我并不想把其他rust的项目比下来。所有actix 名下的项目,无论是actix-web还是 actix-net 我都花心思设计了,api也好,框架也好。每个项目我至少重写4-5次。我延伸了一些需求,一些新的写项目的方式与规律。我希望其他人看我的项目们的源码后收到启发,更上一层楼。现在我觉得支持actix没意思,在rust社区没意思。

我不干开源了。

备注:
我把actix-net 和 actix-web放到我私人的github上了。过几天做决定。我不想我的东西变成幽灵般的存在,新的维护人员需要明白都该怎么办,忙与其他项目的不合适。我现在的打算是把项目设到私人然后删除,所有目标(benchmark)都终于会被删除。除非有人有更好的主意。

所有事情都尘埃落定了,一路很有意思但现在该翻篇了。生活本该活的有意思。

对于Nikolay的最终决定,我只能表示理解和尊重。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号