< 返回版块

Cupnfish 发表于 2020-07-30 21:16

Tags:amethyst,fixed_vec,firefox,webassembly

fixed_vec一个减少数组冗余边界检查的库

rust的Vec在使用索引的时候总会触发边界检查,在某些时候降低了程序的性能。通常解决方法是尽可能使用迭代器来处理数组。

本文通过Ghosts of Departed Proofs这篇论文中讨论的技术来减少Rust中冗余边界检查。

具体内容

在文末有提到了性能差距,如果只想看看效果如何的,可以直接跳到文末

代码示例

use fixed_vec::{name, FixedVec};

let v = vec![0u32; 10];
let v = name!(v);
let mut v = FixedVec::fix(v);

// Perform the two index checks here:
let index_a = v.check_index(...).unwrap();
let index_b = v.check_index(...).unwrap();

for _ in 0..100 {
    // These do *not* perform bounds checks!
    // At compile time, v and index_a must match
    *v.get_mut(index_a) += 5;
    *v.get_mut(index_b) += 10;
}

let v = v.unfix();

// continue using v...

Github仓库

Rust 标准库准备从 libbacktrace 迁移到 gimli

主要是移除了libgcc.so 的依赖,换成了纯 Rust 的gimli

https://github.com/rust-lang/rust/pull/74682

https://github.com/gimli-rs/gimli

消息来自 Google 工程师Benjamin的推:https://twitter.com/Brittain_Ben/status/1288193388588740615

Firefox 79现在支持WebAssembly线程和引用类型!

这是一个很大的进步,意味着Rust的借用检查器可以在web里大展拳脚了。

Read More

在油管发现一个专门更新Rust实战相关视频的博主

视频内容大概有actix、rocket等一系列web线管的实战视频,挺有意思的。

油管博主主页:Genus-v Programming

B站有人搬运:Rust web框架教程

Amethyst更新了一个地图编辑器

在github该仓库页面有地图编辑器的使用示例

Amethyst是rust编写的游戏引擎,最近一年的更新动静较小,主要是集中力量完成了对wasm的支持。在一月份对wasm支持之后开始有了点动静。

Github仓库

Richter雷神之锤游戏的Rust实现

图形后端用的是wgpu

目前正在积极开发中

主页

Github仓库

Deno最近更新了typescript使用的编译器

Deno现在使用SWC(一个Rust写的TS/JS编译器),类型剥离的性能从之前的大约1s变成了现在的大约70ms

Read More

为Linux系统打包Rust项目

文章分为两部分,第二部分还没有发出来

Read More

hawk: Rust 在物联网领域的一个学习案例

hawk 是Knoldus公司的一个 Rust 应用案例,它是一个物联网安全门禁系统。基于Rust、S3、Rekognition、Lambda等服务实现,这些都是亚马逊提供的云服务。

整个项目的逻辑是这样的:

门禁卡那有个树莓派,给雇员拍一张照片,然后雇员的RFID 卡扫描以后,会触发树莓派里的照片上传到S3,然后通过lambda根据雇员id,去另一个S3里调用员工的照片,然后用 第三方图片识别服务,把树莓派拍摄的照片和S3里存储的照片进行相似性比对,返回一个分数,返回到树莓派上面,这个值大于一定值就开门。

项目的源码不是很多,可以学习下。

Read More

Github仓库

rusty days活动

活动地址

部分录播地址the rust borrow checker 大概在2:24左右开始

关于2021-edition:

这两天刚举办的rusty days线上 Rust 大会,steve 讲了一个Topic,需要有2021-edition吗? 这里做一些关键点梳理:

  1. 里面提到 Edition 的作用范围: 允许增加新的关键字,改进语法,但不允许去对语言一致性、标准库等进行根本性破坏。

  2. 回顾编译器的编译过程: a. rustc 是多道编译器,从源码到 AST -> HIR(大部分检查、类型检查、方法查找) -> MIR(借用检查) -> LLVM IR b. rustc 是 基于查询 (query-based) 的编译器

  3. 对于 编译器来说,所有 Edition 的代码,在 MIR 层面都不允许存在差异,即, MIR 是多个Edition的通用语言。 对于 人类开发者来说,Edition 之间会有差异,但不会太多。生态系统也不会搞的像主版本变化那样分裂。

  4. Rust 的发布周期是比较固定的,Nightly是每晚,beta和stable是每六周发布一版。但是 Edition现在还没有确定。那什么时候用 Edition呢? 回顾过去的Rust 2018,可以说是即成功又不成功。 成功是说,Rust 团队达成了既定目标,并且完成了一个艰巨的任务。 不成功的地方在于,发布的东西其实并不是计划的全部,并且团队成员长期工作带来了巨大的疲劳和怠倦。 Rust 团队想做的太多,但是他们低估了投入成本。

  5. 不过,steve表示, 我们应该有一个 Rust 2021 Edition。但它应该比Rust 2018更小的版本,小版本优点会大于缺点。并且在未来保持一个「发行列车」,即便三年内没有什么大的特性,也会坚持发布一个Edition。 对于不使用 Rust 的人,不应该来频繁地关注Rust Edtion的发布信息,他们只需要知道 Rust 已经很稳定就够了! 对于使用Rust的人来说,每三年的 Edition,其实就是一个 「总结」。

  6. 2021 edition 应该有什么特性呢? steve表示其实他并不在意,不必要非得刻意规定什么特性来证明Edition的合理性,哪怕有一个特性错过了发布,那么三年后发布就可以了。 但是,Rust 官方会在 10月份以后发布一个 RFC 的,目前主要是 Niko 和 Steve 在做这个,当然,Niko 还是主力担当。

  7. 为什么是三年呢? 一年一次有点过,五年一次太长,三年节奏刚刚好,这一点 c++ 已经证明了。

视频地址 注意这个视频是 33 分钟以后才开始的

首届 Rusty Day 线上大会散记: 深入借用检查器

分享者:Nell Shamrell-Harrington ,Mozilla员工

该Topic议程分为两部分: Rust编译器概述 和 深入借用检查器

Rust 编译器概述:

介绍了编译阶段:词法、解析、语义分析、优化、代码生成

Token -> AST -> HIR -> MIR -> LLVM IR

在 AST 阶段主要做的工作:宏展开、去糖、处理各种模块导入 HIR的数据结构: Crate(CrateNum) < Definition(DeId) < Node (HirId) > > MIR 的数据结构: Control Flow Graph < bb0(statement -> statement -> terminator ) -> bb1(statement -> terminator ) -> bb2 ((statement > terminator )... >

详细内容可以参阅: https://rustc-dev-guide.rust-lang.org/

优化主要在 MIR 和 LLVM IR 阶段完成,最终由 LLVM IR 通过 LLVM 生成机器码。

深入借用检查:

借用检查器的工作:

  1. 跟踪变量的初始化和move
  2. 生命周期推导(Lifetime inference) a. 变量的生命周期 b. 引用的生命周期。如果引用一个值,则该引用的生命周期不能超过该值的作用域。
  3. 还有很多其他功能,继续参阅rustc dev guide。 (比如 检查不可变和可变借用等)。 https://rustc-dev-guide.rust-lang.org/borrow_check.html

(看完后发现,好像也没有很深入)

视频地址 注意这个Topic 在 2小时以后

Stackoverflow里有人探索Rust中的函数指针魔法,写出了一个奇怪的东西

从代码看上去似乎是通过函数空指针调用了函数

代码Playground

fn foo() {
    println!("This is really weird...");
}

fn caller<F>() where F: FnMut() {
    let closure_ptr = 0 as *mut F;
    let closure = unsafe { &mut *closure_ptr };
    closure();
}

fn create<F>(_: F) where F: FnMut() {
    let func_ptr = caller::<F> as fn();
    func_ptr();
}

fn main() {
    create(foo);
    
    create(|| println!("Okay..."));
    
    let val = 42;
    create(|| println!("This will seg fault: {}", val));
}

作者本人对这部分代码能够正常运行感到疑惑,特别是为什么foo函数能够被caller<F>()函数里强制转化成nullptr调用。

已经有大神对这个问题做出了解释,太长了我直接贴地址。中文社区的大佬如果对这个问题感兴趣,可以帮忙在这里回复一下。

可能有小伙伴访问StackOverflow比较缓慢,这里我复制高赞回复的原文:

This program never actually constructs a function pointer to anything but caller- it always invokes foo and those two closures directly. Every Rust function, whether it's a closure or a fn item, has a unique, anonymous type. This type implements the Fn/FnMut/FnOnce traits, as appropriate. The anonymous type of a fn item is zero-sized, just like the type of a closure with no captures. Thus, the expression create(foo) instantiates create's parameter F with foo's type- this is not the function pointer type fn(), but an anonymous, zero-sized type just for foo. In error messages, rustc calls this type fn() {foo}, as you can see this error message. Inside create::<fn() {foo}> (using the name from the error message), the expression caller::<F> as fn() constructs a function pointer to caller::<fn() {foo}>. Invoking this function pointer is the same as calling caller::<F>() directly, and this is also the only function pointer in the whole program. Finally, in caller::<fn() {foo}> the expression closure() desugars to FnMut::call_mut(closure). Because closure has type &mut F where F is just the zero-sized type fn() {foo}, the 0 value of closure itself is simply never used(注释1), and the program calls foo directly. The same logic applies to the closure || println!("Okay..."), which like foo has an anonymous zero-sized type, this time called something like closure@src/main.rs:2:14: 2:36. The second closure is not so lucky- its type is not zero-sized, because it must contain a reference to the variable val. This time, FnMut::call_mut(closure) actually needs to dereference closure to do its job. So it crashes(注释2)

注释1 Constructing a null reference like this is technically undefined behavior, so the compiler makes no promises about this program's overall behavior. However, replacing 0 with some other "address" with the alignment of F avoids that problem for zero-sized types like fn() {foo}, and gives the same behavior!) 注释2 Again, constructing a null (or dangling) reference is the operation that actually takes the blame here- after that, anything goes. A segfault is just one possibility- a future version of rustc, or the same version when run on a slightly different program, might do something else entirely!

后续还有不少回复,能直接访问StackOverflow的建议查看原文

Read More

From 日报小组 Downtime Jancd

社区学习交流平台订阅:

评论区

写评论
whfuyn 2020-07-30 23:01

赞!内容好丰富

1 共 1 条评论, 1 页