- 主题:请教个rust基本问题,Rc<RefCell<T>>有啥坏处?
这用法就好比把 js 迁移到 ts,然后所有类型都声明成 any,有啥意义呢?
【 在 beep (菜M.喵星耗子) 的大作中提到: 】
: 之前业务是python写的,要加速,尝试了一阵子c++,受不了了,所以才转rust。。。
: 哪怕rust里用Rc+RefCell很多,也比c++强吧?
--
FROM 203.211.111.*
ts 只是加了编译期的类型检查,只有个别语法比如 enum 会生成额外的内容,如果目标版本设定为 esnext,基本上就是代码原封不动
另外快是怎么定义的?v8 目前不比 jvm/golang 差太多,常规 micro benchmark 几乎差不出2倍。本来就快不了多少,再加上通过 js 才能调用 wasm,所以实际上 wasm 几乎不可能做到比原生 js 实现快。另外,除了 native 语言,wasm 里面还得带个 gc,这种套娃实现怎么可能更快?
我说过很多遍了,wasm 的出现并不是 js 的替代品。相反的,对于想移植浏览器、但不想再写一遍代码更有帮助。wasm 根本就是对 js 的补充,两者的发展是相互促进的作用。
另外,ts 目前还是有点尴尬的。由于本来带类型信息,理论上编译器、runtime 可以做更激进的优化。然而实际情况却是擦除类型信息,而使用更保守、更通用的 js 优化
【 在 No1 () No1 () 的大作中提到: 】
: 话说喂给原来的v8这种js运行时的是不是最终只有js,那编译成js的所有语言应该都快不了吧,除非像wasm这种能识别更多数据类型的运行时
--
FROM 203.211.111.*
比 py 快的语言多了,而且 reference count 本身的缺点太多了,要不为啥 gc 是主流
【 在 beep (菜M.喵星耗子) 的大作中提到: 】
: 有意义啊
: 即使多用Rc+RefCell,一方面,和py比,还是要快很多很多的,另一方面,和c++比,好歹RefCell也提供了运行时的内存安全,读写指针冲突的时候会给你panic
--
FROM 203.211.111.*
对于绝大多数“正常”组织来讲,一旦代码处于能用的状态,就基本不会再改动了。所以一般如果有临时代码,那临时代码就成了永久代码了
【 在 adoal (阿豆) 的大作中提到: 】
: 先Rc+RefCell跑起来,以后再慢慢重构成地道的Rust也好……
: 当然,也可能以后就没激情重构了^o^
--
FROM 203.211.111.*
不管是 gc 还是 reference count,上个世纪就已经出现在主流语言和技术里了。这都过去20多年了,还从来没思考过到底是为啥有这些东西?
【 在 hgoldfish (老鱼) 的大作中提到: 】
: 换个角度想,也可能是要求语言带 GC 的程序员有缺点。
: 大家用 gc 习惯了。其实应该思考一下 gc 是怎么来的,以及对 gc 的需求是否可以减免。
--
FROM 203.211.111.*
我不懂 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 FROM 203.211.111.*
FROM 203.211.111.*
跟我对立的观点,要么是这些厂家大量发展基于 refrence count 的技术,要么写 rust 的时候大量使用 Rc。你看懂我在说什么了么,就开始喷?
【 在 tsa300 (Tele-Superachromat T*) 的大作中提到: 】
: 你说的上个世纪就很成熟的手动分配释放内存的技术给业界带来无穷无尽的大窟窿。
: 所以微软谷歌脸书等等企业拼命用rust重写你说的那些成熟的内存管理技术写出来的代码。
--
FROM 203.211.111.*
swift 的速度基本跟 java/go 一档的,通常情况下 java/go 换技术的原因也都是 gc,而不是速度。我不知道 EDA 是啥,只能从更一般情况的情况谈快慢
跟 c++ 一档又带 gc 的选项倒也不是没有,比如 d 语言基本上是能跟 c++ 战的。但是呢,一般来说,大多数技术从走入大众视野,发展到成熟期,一般都在10年左右。d 走入大众视野时,node 和 go 还都不存在,所以它注定是永远小众了。一般 micro benchmark 都不考虑 gc 的影响,我很久没关注过 d 了,不知道它的 gc 目前是什么样的状态。
内存管理就这样,不手动的话,一共就3种主流技术:gc、rc、raii。都是上个世纪就存在的技术,各有各的优缺点,但没有免费的午餐。
个人认为,rc 是最差的,比手动管还糟。因为理论上,手动和 gc 是要么全管,要么全不管。而 rc 是只有一部分要手动管,还不像 gc 那样界限很清楚,只有非内存的资源要手动。我不知道有没有工具可以协助发现循环引用的问题,所以个人结论就是,极度依赖人肉。而不想手动管理的出发点就是,只要是人就会犯错,不管多高的高手,总会有翻车的时候。既比手动更依赖人肉,又有 overhead,结合了两者的缺点,所以是最糟糕的。
raii 能处理的情况非常有限,所以 rust 给出了一系列的严格规定,目的就是满足它的范畴。一旦超过了,要么 unsafe,要么 rc,都放弃了 raii 的好处。我不懂 c++,论坛看到的,c++ 几乎能完成 rust 的全部 raii 功能,但缺少最重要的编译器的严格检查。
我的建议还是 rust,但不要用 Rc,一开始写起来肯定会头疼。但从论坛反馈来看,普遍经历一段痛苦期后就习惯了。而且回头再写 c++ 也会不自觉的意识到问题,写出质量更高的代码。我个人是一直想入坑,但一直停留于想法,所以没法给出个人体会。另外,rust 的主流用法也是偏 fp 的(iterators over for loops),想正经写好本来也要一定时间的适应,所以直接 hard mode 开搞吧
【 在 beep (菜M.喵星耗子) 的大作中提到: 】
: 这里关键考虑还是性能。
: 我原来的理解是,EDA这类场景只能从c/c++/rust里面选,这三个的速度基本是可比的。go也算快的,但是典型计算场景下还是会比第一档的语言慢几倍。你所说的swift慢不到哪里去,具体有benchmark可以参考吗?
: 只要有可能,当然是希望能写有gc的语言啊,但是这不是第一档语言里都没gc嘛。。。。。。c c++ rust 各有各的恶心之处。。
: ...................
--
FROM 203.211.111.*
我当然知道 raii 是从 c++ 来的,不然为啥说是上个世纪就存在的技术。
循环引用的问题是,结构一旦复杂起来,人肉很难意识到哪里产生了循环引用。如果没有编译期的检查,或者即使 runtime 有可以检查的功能,但并没有调用到,那就还是只能靠人肉。
至于数据结构,按照脚本语言的经验,有 Vec 和 HashMap,可以避免很大一部分自定义的复杂结构。而且一般意义上的数据结构,除非太冷门一般都会有现成的库可以用。如果能避免使用 Rc 的话,还是尽量 raii,这样才能最大化利用编译器带来的好处。如果无脑直接抄 poc 项目的代码,上来就优先考虑 Rc,那真的没啥必要非得 rust。用 c++ 不也一样可以直接翻译代码么,都是从零开始还能麻烦到哪去
【 在 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 203.211.111.*