#StdExtend
Repo: https://github.com/sivadeilra/vec_option
#macro #syn
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
#docs
Dash和Zeal都是著名的编程语言文档集工具
Repo: https://github.com/Robzz/cargo-docset
#async #stream #tokio
Repo: https://github.com/tokio-rs/async-stream
#stackoverflow
问题:
下面代码当
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倍的性能差异了。
Read More: https://stackoverflow.com/questions/57458460/why-is-there-a-large-performance-impact-when-looping-over-an-array-over-240-elem
#Stable
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;
?
语法1.37 Release Notes: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1370-2019-08-15
该贴主提到,他看了Facebook工程总监在CppCon 2017的分享,其中谈到Facebook中经常出现的Bug,他认为,这些Bug是用Safe Rust完全不会写出来的Bug。
以下是这些bug的概述:
std::vector
的索引运算符不进行边界检查。演讲者称之为“可能是每个代码库中问题的最大原因”。Rust's Vec总是进行边界检查,除非您使用Unsafe。std::map
的索引运算符将创建一个默认元素。真奇怪。Facebook发生了两起重大事故,Map显示了一些设置,打印设置时偷偷插入了值为0的新设置。Rust的哈希映射不可能做到这一点。要在Rust中获得这样的行为,您必须使用entry()
API对其进行显式编程。std::shared_ptr
线程安全吗?是像Rc还是像Arc?嗯,这很复杂。它很像Arc,但是如果你实际上在多线程环境中使用它,你仍然有可能出错。Rust既有rc又有Arc,它会阻止你将Rc发送到不同的线程。std::shared_ptr
,并在不保留std::shared_ptr
的情况下对结果进行引用。Rust的借用检查在这里拦住你。std::mutex
的代码,但是实际上它正在创建一个与std::mutex
同名的std::unique_lock
,隐藏它但不锁定它。这里真正的问题是,在C++中,std::mutex没有连接到它所保护的数据,而在Rust中,如果不锁定它,就根本不可能访问受Mutex<T>
保护的数据。演讲中从未提到Rust,但如果里面提到Rust的话,该演讲就是Rust最好的广告了 :D
(Libra 选择 Rust,某种意义上,可能也是苦C++久矣)
#tnef
TNEF 以 application/ms-tnef 类型的 MIME 附件的形式出现在邮件中。
Repo: https://github.com/newpavlov/tnef
#android
头一次知道还有这个App
Read More: https://play.google.com/store/apps/details?id=com.bmco.cratesiounofficial&hl=en_us
#async
供学习使用
Repo: https://github.com/Byron/github-star-counter
#git
自动生成 CHANGELOG.md
Repo: https://github.com/rustic-games/jilu
#tokio
tokio-i3ipc的作者写了篇文章记录了此事,也算是一个升级参考。
#assert
该库可以实现编译时断言。
Repo: https://github.com/nvzqz/static-assertions-rs
From 日报小组 Chaos
日报订阅地址:
独立日报订阅地址:
社区学习交流平台订阅: