关于ruby几种String连接性能的小测试
来源:互联网 发布:九九乘法表javascript 编辑:程序博客网 时间:2024/06/05 04:41
最近开始学习Ruby. 据说“Performance”对于C++程序员来说,就像骨头对于狗一样。看到Ruby里连接String有几种不同的方式,心里面就好奇哪种最快。写了个测试程序如下:
代码:
测试结果:
分析:
1)S+S.....+S
这种方式,实际是调用rb_str_plus(见Ruby源代码: string.c).而rb_str_plus作的事情主要是:
需要拷贝内存的长度:
S+S: 2*S.length
S+S+S: 2*(2*S.length)+S.length=5*S.length
S+S+S+S:2*(5*S.length)+S.length=11*S.length
......
2)"#{S}#{S}....#{S}"
没有找到这种方式的源代码。但是因为测试结果和第三种方式类似,实现方式也应该差不多。我猜测因为第三种方式需要“调用”方法(或者是说发送消息),因而比第二种方式稍慢一点。
3)s=""; s<<S<<S.....<<S
这种方式,实际是调用rb_str_concat(见Ruby源代码: string.c).而rb_str_concat作的事情主要是:
需要拷贝内存的长度:
S+S: 1*S.length
S+S+S: 2*S.length
S+S+S+S:3*S.length
......
需要注意的是:
s=""; 每次都会产生一个新的空字符串
4)s.replace(EMPTY); s<<S<<S<<....S
这种方式,和第三种方式基本相同,除了:
s.replace(EMPTY); 不会每次产生一个新的空字符串。
有趣的是,在Ruby1.8里,String类没有clear方法。在1.9里面才有:http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/189314
结论:
1)一般而言,第四种方式最快,第一种方式最慢。
2)避免Ruby分配过多的新String,可以较明显的提高性能。
3)在性能不是特别重要的情况下,第二种方式最好,因为一般比第一种快,而且只需要一条语句。
代码:
require 'benchmark'
include Benchmark
N=100000
EMPTY=""
S="a"*1000
s=""
bm(1) do |x|
x.report("2-1:") { N.times { S+S } }
x.report("2-2:") { N.times { "#{S}#{S}" } }
x.report("2-3:") { N.times { s=""; s<<S<<S } }
x.report("2-4:") { N.times { s.replace(EMPTY); s<<S<<S } }
x.report("3-1:") { N.times { S+S+S } }
x.report("3-2:") { N.times { "#{S}#{S}#{S}" } }
x.report("3-3:") { N.times { s=""; s<<S<<S<<S } }
x.report("3-4:") { N.times { s.replace(EMPTY); s<<S<<S<<S } }
x.report("4-1:") { N.times { S+S+S+S } }
x.report("4-2:") { N.times { "#{S}#{S}#{S}#{S}" } }
x.report("4-3:") { N.times { s=""; s<<S<<S<<S<<S } }
x.report("4-4:") { N.times { s.replace(EMPTY); s<<S<<S<<S<<S } }
end
include Benchmark
N=100000
EMPTY=""
S="a"*1000
s=""
bm(1) do |x|
x.report("2-1:") { N.times { S+S } }
x.report("2-2:") { N.times { "#{S}#{S}" } }
x.report("2-3:") { N.times { s=""; s<<S<<S } }
x.report("2-4:") { N.times { s.replace(EMPTY); s<<S<<S } }
x.report("3-1:") { N.times { S+S+S } }
x.report("3-2:") { N.times { "#{S}#{S}#{S}" } }
x.report("3-3:") { N.times { s=""; s<<S<<S<<S } }
x.report("3-4:") { N.times { s.replace(EMPTY); s<<S<<S<<S } }
x.report("4-1:") { N.times { S+S+S+S } }
x.report("4-2:") { N.times { "#{S}#{S}#{S}#{S}" } }
x.report("4-3:") { N.times { s=""; s<<S<<S<<S<<S } }
x.report("4-4:") { N.times { s.replace(EMPTY); s<<S<<S<<S<<S } }
end
测试结果:
user system total real
2-1: 1.016000 0.328000 1.344000 ( 1.391000)
2-2: 1.391000 0.422000 1.813000 ( 1.812000)
2-3: 1.562000 0.313000 1.875000 ( 1.907000)
2-4: 1.094000 0.000000 1.094000 ( 1.093000)
3-1: 2.281000 1.015000 3.296000 ( 3.313000)
3-2: 2.516000 0.641000 3.157000 ( 3.187000)
3-3: 2.406000 0.797000 3.203000 ( 3.204000)
3-4: 1.641000 0.000000 1.641000 ( 1.640000)
4-1: 3.859000 1.859000 5.718000 ( 5.781000)
4-2: 2.328000 0.875000 3.203000 ( 3.204000)
4-3: 2.578000 0.813000 3.391000 ( 3.437000)
4-4: 1.906000 0.015000 1.921000 ( 1.922000)
2-1: 1.016000 0.328000 1.344000 ( 1.391000)
2-2: 1.391000 0.422000 1.813000 ( 1.812000)
2-3: 1.562000 0.313000 1.875000 ( 1.907000)
2-4: 1.094000 0.000000 1.094000 ( 1.093000)
3-1: 2.281000 1.015000 3.296000 ( 3.313000)
3-2: 2.516000 0.641000 3.157000 ( 3.187000)
3-3: 2.406000 0.797000 3.203000 ( 3.204000)
3-4: 1.641000 0.000000 1.641000 ( 1.640000)
4-1: 3.859000 1.859000 5.718000 ( 5.781000)
4-2: 2.328000 0.875000 3.203000 ( 3.204000)
4-3: 2.578000 0.813000 3.391000 ( 3.437000)
4-4: 1.906000 0.015000 1.921000 ( 1.922000)
分析:
1)S+S.....+S
这种方式,实际是调用rb_str_plus(见Ruby源代码: string.c).而rb_str_plus作的事情主要是:
rb_str_plus(str1, str2)
malloc memory, length=str1.length+str2.length
copy str1 to new memory
copy str2 to new memory
end
malloc memory, length=str1.length+str2.length
copy str1 to new memory
copy str2 to new memory
end
需要拷贝内存的长度:
S+S: 2*S.length
S+S+S: 2*(2*S.length)+S.length=5*S.length
S+S+S+S:2*(5*S.length)+S.length=11*S.length
......
2)"#{S}#{S}....#{S}"
没有找到这种方式的源代码。但是因为测试结果和第三种方式类似,实现方式也应该差不多。我猜测因为第三种方式需要“调用”方法(或者是说发送消息),因而比第二种方式稍慢一点。
3)s=""; s<<S<<S.....<<S
这种方式,实际是调用rb_str_concat(见Ruby源代码: string.c).而rb_str_concat作的事情主要是:
rb_str_concat(str1, str2)
realloc memory, length=str1.length+str2.length+1
copy str2 to new memory
end
realloc memory, length=str1.length+str2.length+1
copy str2 to new memory
end
需要拷贝内存的长度:
S+S: 1*S.length
S+S+S: 2*S.length
S+S+S+S:3*S.length
......
需要注意的是:
s=""; 每次都会产生一个新的空字符串
4)s.replace(EMPTY); s<<S<<S<<....S
这种方式,和第三种方式基本相同,除了:
s.replace(EMPTY); 不会每次产生一个新的空字符串。
有趣的是,在Ruby1.8里,String类没有clear方法。在1.9里面才有:http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/189314
结论:
1)一般而言,第四种方式最快,第一种方式最慢。
2)避免Ruby分配过多的新String,可以较明显的提高性能。
3)在性能不是特别重要的情况下,第二种方式最好,因为一般比第一种快,而且只需要一条语句。
- 关于ruby几种String连接性能的小测试
- String连接的简单性能测试
- ruby 线程的性能测试
- Ruby 数组排序的几种实现与性能比较
- 几种脚本语言的性能简单测试
- 几种排序的性能测试
- 软件性能测试的几种方法
- 关于String和StringBuilder、StringBuffer的一个简单性能测试
- 关于String和StringBuilder、StringBuffer的一个简单性能测试
- 关于String和StringBuilder、StringBuffer的一个简单性能测试
- 性能测试的小思考
- 关于String ,StringBuffer的性能
- 关于String的性能优化
- 几种常用JSON库的性能测试。
- 银行中间业务平台的几种性能测试方案
- openfire服务器性能测试的几种方法
- openfire服务器性能测试的几种方法
- 替代反射调用的几种方式及性能测试
- [收藏]经常用到的javaScript技术代码(经典)
- Java vs C# —— J2EE与.NET平台关于电子企业的两种设想(7)
- Java vs C# —— J2EE与.NET平台关于电子企业的两种设想(6)
- Java vs C# —— J2EE与.NET平台关于电子企业的两种设想(5)
- Java vs C# —— J2EE与.NET平台关于电子企业的两种设想(4)
- 关于ruby几种String连接性能的小测试
- Java vs C# —— J2EE与.NET平台关于电子企业的两种设想(3)
- Java vs C# —— J2EE与.NET平台关于电子企业的两种设想(2)
- Java vs C# —— J2EE与.NET平台关于电子企业的两种设想(1)
- js: select列表值的添加删除
- asp:(0X80004005)操作必须使用一个可更新的查询”错误的解决办法
- Endorsed Standards Override Mechanism
- Java vs C# —— 且看微软的.Net和Sun公司的J2EE如何对垒
- Java vs C# —— JSP与ASP.NET简单之比较!