VecOption: 与Vec<Option<T>>
等价但更高效的库
Repo: https://github.com/sivadeilra/vec_option
Syn 和 Quote 1.0 发布
Syn 和 Quote 此次 1.0 稳定,意味着API接口稳定,但是,并不代表着Rust的语法树稳定。Syn和Quote内部还是会随着Rust的变化而改动,只不过不会影响 Syn 和 Quote 的 API稳定。
注意: Syn和Quote的1.0版本最低依赖Rust 1.31版本。发布日志里还记录了一些Break change,需要注意。
Read More: https://github.com/dtolnay/syn/releases/tag/1.0.0
cargo-docset: 可以生成支持Dash和Zeal的文档集
Dash和Zeal都是著名的编程语言文档集工具
Repo: https://github.com/Robzz/cargo-docset
async-stream: 提供了stream!宏方便编写异步流
Repo: https://github.com/tokio-rs/async-stream
### 「SO问答」对超过240个元素的数组进行循环时,为什么会有很大的性能影响?
问题:
下面代码当
CAPACITY >= 240
的时候,与CAPACITY >= 239
相比,性能慢了80倍。Rust编译器专门为240以内的长度做了优化? 使用rustc -C opt-level=3
进行编译。
use std::time::Instant;
const CAPACITY: usize = 240;
const IN_LOOPS: usize = 500000;
fn main() {
let mut arr = [0; CAPACITY];
for i in 0..CAPACITY {
arr[i] = i;
}
let mut sum = 0;
let now = Instant::now();
for _ in 0..IN_LOOPS {
let mut s = 0;
for i in 0..arr.len() {
s += arr[i];
}
sum += s;
}
println!("sum:{} time:{:?}", sum, now.elapsed());
}
解答:
总结:低于240,LLVM完全展开内部循环,可以优化掉重复循环,增加性能。
分析:
这是一个神奇的阈值,超过该阈值LLVM将停止执行某些优化。阈值是
8字节* 240 = 1920字节
(数组是usizes数组,因此长度乘以8字节,假设 x86-64 CPU)。在该问题中的基准测试中,是仅针对长度239执行的一个特定优化,所以导致了巨大的性能差异。
比如这段代码:
pub fn foo() -> usize {
let arr = [0; 240];
let mut s = 0;
for i in 0..arr.len() {
s += arr[i];
}
s
}
你在 godbolt 编辑器中查看生成的汇编代码,比较240和239,会发现有很大区别。比如当239的时候生成:
movdqa xmm1, xmmword ptr [rsp + 32]
movdqa xmm0, xmmword ptr [rsp + 48]
paddq xmm1, xmmword ptr [rsp]
paddq xmm0, xmmword ptr [rsp + 16]
paddq xmm1, xmmword ptr [rsp + 64]
; more stuff omitted here ...
paddq xmm0, xmmword ptr [rsp + 1840]
paddq xmm1, xmmword ptr [rsp + 1856]
paddq xmm0, xmmword ptr [rsp + 1872]
paddq xmm0, xmm1
pshufd xmm1, xmm0, 78
paddq xmm1, xmm0
就是所谓的循环展开: LLVM将循环体粘贴一段时间,以避免执行那些“循环管理指令”,即循环变量的增量,检查循环是否结束和跳转。(可以自行对比一下240的输出)。但是,即便循环不展开,也不会造成80倍的性能差异。所以,实际上那个性能测试代码嵌套循环导致的(LLVM生成的代码基本上首先只执行内部循环(计算总和),然后通过多次累加总和来模拟外部循环!)。最好要使用Rust的惯用法: arr.iter().sum()
,这样就不会产生80倍的性能差异了。
Rust 1.37 预发布测试
RUSTUP_DIST_SERVER=https://dev-static.rust-lang.org rustup update stable
新版本中有一些新特性:
cfg
和cfg_attr
中可以用泛型参数了- 可以对枚举值使用类型别名了
type MyOption = Option<u8>;
fn increment_or_zero(x: MyOption) -> u8 {
match x {
MyOption::Some(y) => y + 1,
MyOption::None => 0,
}
}
- 可以用
_
来定义常量:const _: u32 = 5;
- Rust 2015 edition 的宏现在支持
?
语法 mem::MaybeUninit<T>
和T已经实现ABI兼容,MaybeUninit<T>
共享T的大小、对齐方式和ABI。
1.37 Release Notes: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1370-2019-08-15
Reddit讨论:CppCon 2017 - 在Facebook上反复出现的 C++ bug
该贴主提到,他看了Facebook工程总监在CppCon 2017的分享,其中谈到Facebook中经常出现的Bug,他认为,这些Bug是用Safe Rust完全不会写出来的Bug。
以下是这些bug的概述:
- Bug #1: 越界访问。C++的
std::vector
的索引运算符不进行边界检查。演讲者称之为“可能是每个代码库中问题的最大原因”。Rust's Vec总是进行边界检查,除非您使用Unsafe。 - Bug #2: 如果你搜索的关键字不在map中,那么
std::map
的索引运算符将创建一个默认元素。真奇怪。Facebook发生了两起重大事故,Map显示了一些设置,打印设置时偷偷插入了值为0的新设置。Rust的哈希映射不可能做到这一点。要在Rust中获得这样的行为,您必须使用entry()
API对其进行显式编程。 - Bug #3: 试图避免不必要的复制通常会导致对已经不存在的临时成员的引用(悬垂指针)。C++没有借用检查器来检测这一点。Rust会。
- Bug 4: volatile。它不会使代码线程安全,但是人们还是这样使用它。Safe Rust根本没有volatile。
- Bug 5:
std::shared_ptr
线程安全吗?是像Rc还是像Arc?嗯,这很复杂。它很像Arc,但是如果你实际上在多线程环境中使用它,你仍然有可能出错。Rust既有rc又有Arc,它会阻止你将Rc发送到不同的线程。 - 赠送的Bug : 人们经常解引用
std::shared_ptr
,并在不保留std::shared_ptr
的情况下对结果进行引用。Rust的借用检查在这里拦住你。 - Bug #6: 由于C++语法中的一个怪癖,很容易编写看起来像
std::mutex
的代码,但是实际上它正在创建一个与std::mutex
同名的std::unique_lock
,隐藏它但不锁定它。这里真正的问题是,在C++中,std::mutex没有连接到它所保护的数据,而在Rust中,如果不锁定它,就根本不可能访问受Mutex<T>
保护的数据。 - 附送的Bug : 在C++中,很容易意外地对事物进行深度复制(Clone)。演讲者和听众中的一个人理所当然地指出,这真的没什么大不了的,事实上,许多bug(见bug #3)都是通过避免不必要的拷贝而引入的。尽管如此,Rust在这里对你也有帮助,因为如果你想克隆一些东西,你通常需要显式地做。
- 附送的又一个bug:“我们有很多与异步编程相关的生命周期问题,”演讲者说。他称之为“非常关键”和“最重要的缺陷之一”。如果说Rust擅长什么,那就是“与异步编程相关的生命周期问题”。
演讲中从未提到Rust,但如果里面提到Rust的话,该演讲就是Rust最好的广告了 :D
(Libra 选择 Rust,某种意义上,可能也是苦C++久矣)
- Read More: https://www.reddit.com/r/rust/comments/cq9rco/cppcon_2017_curiously_recurring_c_bugs_at_facebook/
- CppCon 2017 视频 : https://www.youtube.com/watch?v=lkgszkPnV8g
tnef: 一个纯Rust的 TNEF 解析器
TNEF 以 application/ms-tnef 类型的 MIME 附件的形式出现在邮件中。
Repo: https://github.com/newpavlov/tnef
「非官方」Google Play市场的 Crates.io 安卓App 已经更新到了1.5版本
头一次知道还有这个App
Read More: https://play.google.com/store/apps/details?id=com.bmco.cratesiounofficial&hl=en_us
Rust异步编程尝试:GitHub star计数工具
供学习使用
Repo: https://github.com/Byron/github-star-counter
Jilu: 根据Git仓库的状态生成改变日志
自动生成 CHANGELOG.md
Repo: https://github.com/rustic-games/jilu
tokio-i3ipc更新到了async/await
tokio-i3ipc的作者写了篇文章记录了此事,也算是一个升级参考。
static-assertions-rs 发布 0.3.4 版本
该库可以实现编译时断言。
Repo: https://github.com/nvzqz/static-assertions-rs
From 日报小组 Chaos
日报订阅地址:
独立日报订阅地址:
社区学习交流平台订阅: