有多少人入门的时候被默认低性能的字符串连接方式坑得不浅的

2019-12-14 14:14:12 +08:00
 crella

自己用到 ruby 的字符串连接的时候,从'str1 += str2'号改成'str1 << str2',感觉就像翻身农奴把歌唱一样,速度快了十倍,内存消耗小了约一半……

本来是联想到 c#的 Stringbuilder,然后上 stackoverflow 看看 ruby 连接字符串时被吐槽的地方,看到了'<<'号,就试一试,效果很好。因为懒得打字,所以我写 Array.push(obj)都改成 Array << obj 的形式了。

又找到了个比较详细的解释: https://www.xuebuyuan.com/1256522.html

某些新手教程不深入讲字符串连接。

4014 次点击
所在节点    程序员
18 条回复
memedahui
2019-12-14 14:20:29 +08:00
快忘光了,随手翻翻手中的汇编指南
nulIptr
2019-12-14 14:38:24 +08:00
不要一刀切,很多时候直接用+可以被编译期优化掉,尤其是拼 sql 的时候
dbpe
2019-12-14 14:40:41 +08:00
emmmm..这些不是应该能被编译器优化掉么....
Bromine0x23
2019-12-14 15:04:52 +08:00
再本质点的话是因为 a += b 只是 a = a + b 缩写,也就是没有修改原本的 a 对象,而是用生成的新对象替换了 a 的引用
Raymon111111
2019-12-14 15:15:49 +08:00
既然大多数人都用 str1+str2 这种写法, 而且这种写法看起来简洁直观, 那编译器应该对它进行优化

(就和 java 一样, 单纯的字符串拼接加号是最快的, 除了放在循环里
maomaomao001
2019-12-14 15:49:00 +08:00
如此简单的事情,居然编译器不能优化? 居然还要手动自己调 ? 应该不会吧
agagega
2019-12-14 16:52:32 +08:00
Ruby 现在不都 Rope 了么?而且这种机会应该可以被优化掉了
zunceng
2019-12-14 17:01:30 +08:00
@nulIptr 抓到一个拼接 sql 的 大家快去试 sql 注入他的库
crella
2019-12-14 17:05:05 +08:00
@Bromine0x23 你一说我才想起。

比如 a=1; 10.times {a += 1;}; a.object_id =>23

已知 1.object_id = 3,2.object_id = 5,则 23=10*2+3。

真是让人觉得奇怪。
crella
2019-12-14 17:22:29 +08:00
顺便做个笔记吧。

a=5; a.object_id == 5.object_id => true

ObjectSpace._id2ref(a.object_id) == 5 => true
Bromine0x23
2019-12-14 19:22:02 +08:00
@crella 没什么奇怪的,对象 ID 空间就是这么规定的 https://github.com/ruby/ruby/blob/v2_6_5/gc.c#L3258
zappos
2019-12-15 02:16:21 +08:00
@nulIptr 插值啊,插值是干嘛用的
crella
2019-12-15 07:20:17 +08:00
@zappos 我在 ruby 里面试验,插值法比+=还要慢。

代码见 https://dpaste.org/T1vR

我也很早就发现 ruby 确实比其他语言奇怪一些……
msg7086
2019-12-15 07:56:45 +08:00
顺便一提,原本 Matz 是打算在 Ruby 3 里默认冻结字符串常量的,所以当你在旧版本里开启 frozen_string_literal 提前享受这份快乐的时候,是不能对字符串做 << 操作的。不过后来 Matz 后悔了,于是 Ruby 3 不打算默认冻结了……

另外各方面都比较好的做法是用数组做 StringBuilder,即
c = ['start']
10000.times { c << "-con" }
c = c.join

这种做法在没开 frozen string 的时候用时只比<<慢 60%,开了 frozen 以后比<<快 5%,比插值和+=都快得多。
yannxia
2019-12-15 09:50:18 +08:00
以前 JavaBoy 也经常有这样的困扰。
nulIptr
2019-12-15 12:40:24 +08:00
@zappos c#里面 string.format 和$插值就是+
zappos
2019-12-15 16:52:11 +08:00
@nulIptr 但是 string.join 是计算好长度然后分配一个 char* 再拿它初始化 string。很谜。
ColinZeb
2019-12-15 23:20:52 +08:00
@zappos C#里的+貌似等同于 string.concat

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/629008

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX