- 主题:请教个rust基本问题,Rc<RefCell<T>>有啥坏处?
嗯,如果之后用一段时间发现需求稳定了,不需要Rc的地方应该是可以把Rc撤掉换成普通引用的
【 在 adoal (阿豆) 的大作中提到: 】
: 先Rc+RefCell跑起来,以后再慢慢重构成地道的Rust也好……
: 当然,也可能以后就没激情重构了^o^
--
FROM 123.120.160.*
我目前的理解是,即使多使用Rc+RefCell,性能也基本会和c++ shared_ptr可比的。现代c++也已经是unique_ptr shared_ptr满天飞了。
需求就是要快呀,传统上EDA软件基本都是c++写的,现在用rust我觉得是合理的,据我所知那几个EDA大厂比如s家里面也用很多rust。用golang反而很奇怪。。。
【 在 eGust) 的大作中提到:
: 比 py 快的语言多了,而且 reference count 本身的缺点太多了,要不为啥 gc 是主流
--
FROM 123.120.160.*
说实在的不带gc的语言写起来太操心了。。。
【 在 hgoldfish (老鱼) 的大作中提到: 】
: 换个角度想,也可能是要求语言带 GC 的程序员有缺点。
: 大家用 gc 习惯了。其实应该思考一下 gc 是怎么来的,以及对 gc 的需求是否可以减免。
--
FROM 123.120.160.*
nim是咋个玩法?没接触过,有关于此的链接吗?
【 在 hgoldfish (老鱼) 的大作中提到: 】
: nim 在探索新路。
: 确实操心。rust 就是一个例子。cpp 程序也经常搞到内存泄露。
: 不过如果一个语言不支持 closure 的话,不使用回调函数,gc 的必要性就没有那么高了。以前 qbasic 语言,功能很受限,那会儿就没什么人担心内存泄露。
: ...................
--
FROM 123.120.160.*
非常好奇没有gc同时还能保证内存安全同时还不加重心智负担的玩法是啥样
【 在 hgoldfish (老鱼) 的大作中提到: 】
: nim 在探索新路。
: 确实操心。rust 就是一个例子。cpp 程序也经常搞到内存泄露。
: 不过如果一个语言不支持 closure 的话,不使用回调函数,gc 的必要性就没有那么高了。以前 qbasic 语言,功能很受限,那会儿就没什么人担心内存泄露。
: ...................
--
FROM 123.120.160.*
这里关键考虑还是性能。
我原来的理解是,EDA这类场景只能从c/c++/rust里面选,这三个的速度基本是可比的。go也算快的,但是典型计算场景下还是会比第一档的语言慢几倍。你所说的swift慢不到哪里去,具体有benchmark可以参考吗?
只要有可能,当然是希望能写有gc的语言啊,但是这不是第一档语言里都没gc嘛。。。。。。c c++ rust 各有各的恶心之处。。
【 在 eGust (十年) 的大作中提到: 】
: 标 题: Re: 请教个rust基本问题,Rc<RefCell<T>>有啥坏处?
: 发信站: 水木社区 (Wed Dec 8 15:55:43 2021), 站内
:
: 我不懂 c++,但 reference count 的缺点放哪都一样,weak reference 的分析完全交给人肉。手动分配释放内存的话,至少上个世纪就有很成熟的技术,可以追踪内存泄露是在哪里分配的,重复释放的代码也很容易找。如果想追踪循环引用是如何产生的,难度不比实现一个 gc 更简单,反正我是不知道有没有成熟的技术可以用。
:
: 至于速度,swift 自然也没慢到哪去;virtual method 也一样有开销,绝大多数情况下都不会产生质的影响。所以还是那句老话,干嘛非要用一个看似更安全的技术,来写一个实际上更糟糕的实现呢?
:
: 【 在 beep (菜M.喵星耗子) 的大作中提到: 】
: : 我目前的理解是,即使多使用Rc+RefCell,性能也基本会和c++ shared_ptr可比的。现代c++也已经是unique_ptr shared_ptr满天飞了。
: : 需求就是要快呀,传统上EDA软件基本都是c++写的,现在用rust我觉得是合理的,据我所知那几个EDA大厂比如s家里面也用很多rust。用golang反而很奇怪。。。
:
:
: --
:
: ※ 修改:·eGust 于 Dec 8 15:59:47 2021 修改本文·[FROM: 203.211.111.*]
: ※ 来源:·水木社区 mysmth.net·[FROM: 203.211.111.*]
--
修改:eGust FROM 203.211.111.*
FROM 123.120.160.*
嗯,rust里面也可以考虑用arena
【 在 jjfz (每天两壶茶) 的大作中提到: 】
: EDA里面很少用到shared_ptr啊,核心数据都是ObjPool管理
: 很多时候还得用mmap自行管理内存页面
: 这种开发模式下,绝大多数人只是使用指针,不会create/destroy Obj的
: ...................
--
FROM 123.120.160.*
多谢长篇回复!
: 我不懂 c++,论坛看到的,c++ 几乎能完成 rust 的全部 raii 功能,但缺少最重要的编译器的严格检查。
多解释两句,rust的raii就是从c++抄来的,Box就是unique_ptr,Rc就是shared_ptr,几乎一样。在变量生命期方面,rust就是比c++多了一个“默认move语义”,而c++默认是copy语义。这一点需要习惯。因为默认move,所以编译期rust会给你检查是否使用了已经moved变量,提前警告。
: 我的建议还是 rust,但不要用 Rc,一开始写起来肯定会头疼。但从论坛反馈来看,普遍经历一段痛苦期后就习惯了。
rust里的Rc和普遍所说的ref count可能还有点角色上的不一样。rust里面有严格的所有权检查、读写引用冲突检查,所以其他语言里有些场合,不用rc也可以,但是在rust里,为了满足所有权传递和读写引用的要求,就必须要用rc,否则就要重新设计数据结构,甚至要对功能进行删减。
举一个例子,如果想要设计这样一个api:
struct S { f: i32 };
let mut s1 = S { f: 1 };
s1.inc().inc(); // [1] 支持先let出变量,再链式调用chain
let s2 = (S { f: 2 }).inc().inc(); // [2] 也支持先链式调用chain再初始化变量
那么怎么设计这个inc方法呢?
impl S { fn inc(mut self) -> Self { Self {f: self.f + 1} };
这样传所有权的话,只满足[2],不满足[1],因为[1]的情况下这么写 s1 就被 moved 了。
impl S { fn inc(mut& self) -> mut& Self { self.f += 1; self };
这样传引用的话,又不满足[2],因为返回的引用所指的self的生命期不够长。
这种时候貌似只能让inc返回一个Rc<S>,通过低成本的Rc::clone来满足这个api的设计要求。
另外,任何有环的数据结构,也是不可能使用RAII解决全部问题的,必须要引入Rc和Weak,人肉来操心,或者把整个数据结构看作一个整体,用arena的思路解决问题。
【 在 eGust (十年) 的大作中提到: 】
: swift 的速度基本跟 java/go 一档的,通常情况下 java/go 换技术的原因也都是 gc,而不是速度。我不知道 EDA 是啥,只能从更一般情况的情况谈快慢
: 跟 c++ 一档又带 gc 的选项倒也不是没有,比如 d 语言基本上是能跟 c++ 战的。但是呢,一般来说,大多数技术从走入大众视野,发展到成熟期,一般都在10年左右。d 走入大众视野时,node 和 go 还都不存在,所以它注定是永远小众了。一般 micro benchmark 都不考虑 gc 的
: 内存管理就这样,不手动的话,一共就3种主流技术:gc、rc、raii。都是上个世纪就存在的技术,各有各的优缺点,但没有免费的午餐。
: ...................
--
FROM 166.111.77.*
嚓,竟然m了
【 在 beep (菜M.喵星耗子) 的大作中提到: 】
: 多谢长篇回复!
: 多解释两句,rust的raii就是从c++抄来的,Box就是unique_ptr,Rc就是shared_ptr,几乎一样。在变量生命期方面,rust就是比c++多了一个“默认move语义”,而c++默认是copy语义。这一点需要习惯。因为默认move,所以编译期rust会给你检查是否使用了已经moved变量,提前警
: rust里的Rc和普遍所说的ref count可能还有点角色上的不一样。rust里面有严格的所有权检查、读写引用冲突检查,所以其他语言里有些场合,不用rc也可以,但是在rust里,为了满足所有权传递和读写引用的要求,就必须要用rc,否则就要重新设计数据结构,甚至要对功能进行删
: ...................
--
FROM 123.120.160.*
多谢纠正,边开会边手敲的,没过脑子。。
【 在 No1 的大作中提到: 】
: 不明觉厉
: 感觉本帖子链里唯一有真东西的一个
: 不过举的例子有点小问题应该没让编译器把关吧:
: ...................
--
FROM 223.104.39.*