我曾经喜欢C和C ++。 如果我们追溯到90年代中期,我使用了C语言,可能是我认为C ++很棒,而汇编语言完全是我进行逆向工程/安全工作的一部分。
注意所使用的指令和数据的价格会带来直觉,安全和) I V信心。 您将获得低层次的构建块,构建自己的构建块,并且因为存z 3 : 8 E 6 E - P在\"零成本\"的概念,或者至少直接控制成本,因此为此付出的代价很少。 您几乎没有活动部件,而众u @ J n F所周知-这是简单设计的强大特征。
在我的职业生涯中,我也花了很多u 7 } x 5 V C }时间从事.NET(C#,F#)和JVM(JavaV 3 X,Scala以及后来的Kotlin,作为更浅的Scala)。 这些是静态类型的,垃圾回收的语言,其语言已演变为最先进的虚拟机。 我还使用了Ruby和Javascript的现代版本(Typescrs } _ O Q / r a mipt,ESnext),或更通i L 5 $ 5 $ X用的编程语言,这些语言具有出色的开发人员经验。 毫不奇怪-这也使我也使用了函数语言。
然后,在2010-2011年左右,我发现了一个异常值-Go。 没有函数,没有动态,感C 1 L B 9 ; $ g觉像家(家是C)。 当Node.js让我失败时,我成功地将~ @ G基于Go的系统从早期的Go版本构建并Z 6 v投入生产(我8 b 4 F记得大约一年后,Segment.io公开了他们从Node.js到Go以及其他版本的迁移) 。
我想我觉得Go可以在几乎零投资和出色的开发人员经验之间实现强大的系统编程和出色的性能之间的平衡。 90年代的某些感觉,以及许多现代的奇妙开发实践。
但是有一个原因让我怀旧W Z , (,并且让您阅读所有内容,这使我想到了Rust应该了解的前两件事。
1.你必须做好承诺
对我来说,Rust在上面的内存通道上漫步,从所有这些语言中挑选并带走@ : $ } N l i了最好的体验,这真是令人难以置信的疯狂成就。
为了付出所有这些伟大的事情(就像我想的那样),它U h O K B ( ( )伴随着R n 8 k V人们通常感到烦恼的东西-借阅检查器和重新出现的东西(看着您逐渐打字!)-静态打字。 这意味着,如果您正在使用可使用GC和/或使用动态f x s X l Z % J语言的环境中,请准备好投入大量的时间来思考和设计有关内存和类型的管Y r x ; C理,以及通常的这种体验- 缓慢,安全的思考。
这是另一个曲线球–编译我的一个较大的Rust项目大约需要30秒,而类型检查周期大约需要3秒。 太糟糕了,当我从Rust转到Go时,我的大脑需要几分钟来适应Go的编d i 2译速度; 我键入Go代码,然后凝视屏幕,等待编[ p Z 4 & 3译器赶上来,只是在我键入:)时它立d N 9即被捕获。
我相信您会发/ ^ q = f m 6 ( S现自己的挑战; 这给了我最好的Rust建议,我可以给你。
准备提交。 不要期望会参与其中,编写代码并赢得胜利,尤其是在开始时。 期望能投入,落在你的脸 ! * 6 H k E F (上,大量的面部掌上,编写代码,并在计划投资的时间的两倍之后出局(更像是十倍,但我不想显得沮丧)。
这使我想到了Rust的第二个最佳建议:从头开始生存。
用伟大的约翰卡马克(John Carmack)的话来说,Rust代码感觉非常健康。
2.Rust有9 z R益健康
如果您打算深入研究Rust,那么这是您应该开始的目标-如果您来自动态语言,静态和垃圾收集语言或静态和手动内存托管语言。
关于Rust如何\"感受\"的主要讨论点之一是借贷检查程序和所有权。 这- & ( ! [ t i c是我的Rusa k w 1 W `t收养者和借入检查者的临时生命周期。
跟它对干
差点丢了
同意
拥抱它
明白它
来自& / = : S动态语言
这对您设计和构建软件的方式而言意义重大。 由于借阅检查器和静态键入,您的设计需要牢固地固定到位,并且\"留待以后使用\"的空间很小。
这意味着借阅检查器会不时告诉您您的设计很臭。 有时,您将代码移到哪里来满足借阅检查程序并不重要-经过数小时的努E # T f力,只有K ] O在退后几[ P . J :步然后再进行处理之后,您才会意识到设计存在根本缺陷。 您可以通过克隆,复制和装箱来协商重新设计的方式,如果幸运的话,就足够了。
如果您比较幸运,那么实际上您将进行重新设计,这将迫使您查看对象图,职责和依赖性,这时您将最终获得Rust。
来自静态语言,垃圾回收
使用借阅检查器会让您感到大部分痛苦,就好像您来自动态语言一样,只是现在您必须取消学习部分静态类型直觉,并且很难学习。
Rust会感到古怪和样板。 而且,如果您无法克服它,请尝试挑战构建的内容-| S a是否必须使用Rust构建? 您是否要使用系统编程语言来构建? 您是否需要一个可预测的内存模型,零~ ! g ,成本,出色的性能(可Y $ J `以说c 8 d L,您已经可以通过使用良好的VM来获得,以内存换取性能)? 也许不吧。 更好地R p Y选择适合工作的工具。
来自静态语言,手动内存管理
如果您来自C ++,那么进m H y W入Rust不久后,您会觉得自己已M 经换了一双新鞋; 我说\"很快\"而不是\] T $ / S H"立即之后\"是因为,您的第一印象是Rust将\"为您决定\"太多,然后,我希望货物和时间能完成任务并软化您。
与您完全拥有(并且想要!)完全控制的C ++相比,Rust的某5 _ - 6 ]些感觉就像魔术,您不会同意。 还要记* G ]住,Rust相对来说还很年轻。 您期望存在的生态i G {系统的很S @ 3 i L - R大一/ % , k % X W s部分(来自C ++)并不存在。
3.构建工具的最佳选择
用Rust构建x 6 8 | Y工具是惊人的。 您拥有一个了不起的CLI库,就像一个用于配置,数据结构的令人敬畏的序列化库,以及一个很棒的日志记录库,甚至是免费的安全并行u k ! } h Q k性。 免费安全并行!
其余的包括电池,因为标准库非常丰富。
Rust默认情况下也是高性能和安全的,具有很好的交叉编译故事,并且具有相对紧凑的二进制文件(5到20 mb,在大多数情况下小于Go二进制文件)且启动时间令人e | B %瞠目结舌,这也没有什么坏处。
4.非常适合互操作和替换现有的基础设施
在我看来,Rust的杀手级功能应该是C ++ interop,但这只是我一个。 就像许多尝试与C ++进行集成并挣扎的语言一样,简短的故事y , 2 v G * Y 5 c是它还不完全i k 8 *存在(由于C ++的修改等)。
但是,Rust的FFI和 F L Y q : `直接集成到动态语言的速度很快变得无与伦比,这使其在将C /O Z # H C ++替换为动态语言的性能应用程序的低级语言方面做得很好-但这是我自i 1 p ~ = O己的预测。
5.稳定一致
我很早就开始使用Rust,并分g N D v a享了自己的表白T C 0 v b N-愤怒地抛弃了它。 我无法构建一个能够与语言,包装箱和: s 6 $ : s标准库损坏保持一致的版本。
几年后,当我再次拿起它时,情况就不一样了n Y : P。 我从未遇到过板条箱,依赖项或程序包或构建基础架构的问题! 这是有充分的理由的。
需要那种两极分化1 k D ] r的经验才能将稳定性视为一项非常有价值的功能。
在一个具有大板条箱表面积的项目中,在过去的半年中,我一直在每个周末不断提升夜间防锈性能,而不会出现任何破损,事实上,这在性能和编译时间方面都有所提高!
6.切片和切块软件
一项容易被忽略的RX % i w ! Q # U Zust功能就是函数。 函数使您可以在编译时混合和匹配软件; 您可以根据他们自己的个人限制,发行简化版本,不同许可版本(使用具有不: p g 9 _ j @ $同许可的n B r : ; 3 1 = .不同包装箱),或提供菜单供他人选择。
我将函数用作计划,以从同一代码库发布商业版本和免费版本的软件,以确保免费版本二进制完全没有许可代码。
我还喜欢通过排除其他包装箱中不使用的功能来控制编译时间(稍后会详细介绍)。
7.惊人的性能
干净,2 L ~ j简单的R9 l 3 g F v ] / {ust默认情况下非常快:
每次更新Rust时,我都会看到性能的提升,以至于我期待每周更新Rust(我每晚使用)。
8.在没有生态系统的情况下使用Go For
某些生态系统/ I O O ( D 2 V y尚不存在-很好。 显然,更好的方法是构建并共享缺少的内容,但是当时间紧迫时,我使用Go来完成Rust的故事,方法是按cshared编译go并使用libloading。 Go拥有更丰富的生态系统,在权衡取舍之后,我可以更快地进行迭代。 您必须记住要考虑到构建的复杂性(交叉编译Go代码并确保静态链接了足够多的代码以便轻R s z - G z r 松加载)。
为什么其他所有人都去?
可以编译为俱乐部,并且周围有一个奇妙的交叉编译故事。
到现在已经拥有了巨大的生态系统。
一天即可轻松上手,学习的概念数量很少,因此精神上的负担很低。 快进,快退,回到您的Rust代码。
与Rust共享L / 3 # B O i一些性能特征。
9.编译速度慢
在我看来,这是一个很大的问题。 因此,我也想分享一些技巧来解决此问题。
从全新的: @ !--bin开始,进入编辑器,编译速度非常好,编辑v / 7 % 4 4 m器反馈很快。 添加大约5个板条箱,您将在5秒的区域E x @内进行编译。
快进大中项目,P q t 6 M O您需要30秒的构建时间和大约5秒的货物检查时间,这是我的编辑器(可能还有其他编辑器)将用于快速错误检查的功能,这应该 是为您的快速反馈回路设置曲折曲线的原因。
板条箱破碎
为了加快构建速度,您可以将项目分解成多个部分,然后分别进行编译。 我等了一段时间,宁愿花很多时间来编译,因为我不相信它会顺利进行(但确实会非常顺利);A ~ * 我以为我会走进一个Rust味的兔子洞,以某种方F j O W [式让借阅检查器在% ( . K这一切上占上风。
通过将主项目箱分成四个部分(阅读:将主代码库拆分为多个独立的库),我从痛苦的30秒变为了9秒,现在这9秒中的大部分时间都在链接二进制文件 ` r D $。 事实证明,这是一件轻而易举的事。
通过新的项目布局,我发现了其他好处:
易于识别可选功能。
容易将某些子] e e K & p m M板条标记为功能,但不包括这些功能。
因此,在破碎时会产生很大的力量。 这意味着项目布局在Rust中变得更加重要,因为它是个1 e m人和团队的工作流优化/ f K | e R : _引擎。
与其他语言和现代软件体系结构一样,要干净地分解为板i z o * ~ J j .条箱,请尝试确定您的身份:
核心:数据,类型,抽象
逻辑:算法(可以和核心一起使用)
外围V # 3 S .设5 H 6 L = Z备:网络,HTTP,报告
应用程序:入口点,使用并粘合一切
然后关注ripgrep之类的项目,以实际了解如何使用货物工作区分解您的项目。
这是另一个令人惊奇的意外,它提醒您Rust十分聪明:
4 | use crate::project::Project;
| ^^^^^^^
| |
| unresolved import
| help: a similar pf Q 3 u S ] % nath exists: `aural_engine::project`
如果Ru8 y t Zst在您的代码中看到了寻找本地代码的导入路径,但是现在您已经将它们移到了板条箱中,它将帮助您。
请注意,要享受速| n W e D O m度,您可能必须打开以子面板之一为根的编辑器。 这意味着它将根据该板条箱进行检查; 如果在工作空间根目录下打开} ] 2 R,则编T N x Q $ c y H 辑器(或货物)将在所有依赖项的上下文中进行检查。 即, s 1 z %如果B依赖于A,并且B发生变化,那么货物/铁锈将同时检查B和A,从而取消了板条箱破碎的目的。 但是,如果您在B的上下文中打开项目并更改B,则仅会检查B,即速度。
为了完成有关诊x 3 S断,思考和修复性能的阅读材料,这里有更多的编译器技巧,问题跟踪进度以及如何分析编译器以及其他性能分析和基准测试。
为了获得更好的链接时间,请尝试在操作系统上与LLD链接。 遗憾的是,其中的许多功能在macOS上是不可能的(包括与LLg U 5 A F ( GD的链接)。 为了给您提供有关如何在c O ROSX上进行概要分析的线索(因为它没有perf),请阅读或多或少使用macos-profi8 0 w O X bler或多或少地打包这些说明E a . I :。
10.服务故事仍在进行中
服务,AP! $ L t w ; kI和WeY @ M Pb框架可能是Rust的梦想,但仍在讲述支持它的基础架h ) } @ 7构故事。
我觉得令人兴奋的几个板{ X * U ] : n ~条箱是hyper,tokio和actix) [ 3 b f p。 我已经选择使用actix进行服务了,但是我仍然意识到,这并不是让我在现阶段选择Rust来进行传统后端服务项目的原因。
奖励:文档很棒
您很有可能已经知道了这一点,这就是为什么我不算这个。 人们普遍认为,Rust具有更好的文档记录,并且再次考虑到Rust的存在年限,这确实令人惊讶。 例如,您拥有Rust版本,有效的Rust(尽管在旧书中),以及通过搜索与Rust相关的任何内容而找到的常规文档,也称为\"书\"d t l ] # 9 m。
如果我忽略了L + ~ $ q x CRust仍然是新事物这一事实,很高兴在Rust中看到一个Learnyou变体。
(本文翻译自Dotan Nahum的文章《10 Key Learnings in Rust after 30,000 Lines of Code》,参考:ht7 $ u z R K ; % ^tps://medium.com/@jondot/my-key-learnings-after-30-000-l2 6 # Ooc-in-rust-a553e6403c19)