设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索

【效率测试】Ruby中include方法的效率问题

查看数: 2679 | 评论数: 4 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2015-1-28 13:08

正文摘要:

本帖最后由 寒冷魔王 于 2015-1-28 13:18 编辑 昨天重构了SMRC,新建类Point表示点的坐标,期间运用到了include方法。发现这个版本比上次发布的版本效率要快1倍。 今天调试了半天,终于找到了原因:include方法判 ...

回复

taroxd 发表于 2015-1-30 07:50:19
本帖最后由 taroxd 于 2015-1-30 07:56 编辑

为何不用 Hash 或者 Set?

顺便提一句,数组在算 hash 的时候也很慢。

RUBY 代码复制
  1. require 'benchmark'
  2.  
  3. time = 10_000_000
  4.  
  5. default_proc = -> h, k { h[k] = Hash.new(&default_proc) }
  6.  
  7. hash = Hash.new(&default_proc)
  8.  
  9. array_key = 1,2,3,4,5
  10.  
  11. hash[array_key] = hash[1][2][3][4][5] = 0
  12.  
  13. Benchmark.bmbm do |x|
  14.   x.report("embed key") { time.times { hash[1][2][3][4][5] } }
  15.   x.report("array key") { time.times { hash[array_key] } }
  16. end
  17.  
  18. =begin
  19. Rehearsal ---------------------------------------------
  20. embed key   1.700000   0.000000   1.700000 (  1.704098)
  21. array key  14.633000   0.000000  14.633000 ( 14.631836)
  22. ----------------------------------- total: 16.333000sec
  23.  
  24.                 user     system      total        real
  25. embed key   1.669000   0.000000   1.669000 (  1.665095)
  26. array key  14.493000   0.000000  14.493000 ( 14.530831)
  27. =end

点评

Hash在处理某些问题上没数组方便,而且看ruby源代码发现貌似Array是零散的。与其这么用不如直接C++。话说有没有连续的数组?  发表于 2015-1-30 12:41

评分

参与人数 1星屑 +150 收起 理由
恐惧剑刃 + 150 认可答案

查看全部评分

寒冷魔王 发表于 2015-1-28 15:06:03
本帖最后由 寒冷魔王 于 2015-1-28 15:26 编辑
RyanBern 发表于 2015-1-28 14:24
我的测试结果:

因为机子太慢我改成5000000了TAT


RUBY 代码复制
  1. class Test
  2.   def self.test(string,&block)
  3.     time = Time.new
  4.     block.call
  5.     puts string,Time.new-time
  6.   end
  7. end
  8.  
  9. point = Array.new
  10. max = 10000000
  11.  
  12. Test.test("Push Class Array") { max.times { |i| point.push [i,i] } }
  13. Test.test("Include Class Array") { point.include?([max,0]) } # 取最坏情况
  14. Test.test("Do Class Array") { point.each { |p| break if p==[max,0] } # 迭代+判断 }
  15. Test.test("Do2 Class Array") { point.each { |p| } } # 纯迭代
  16. Test.test("Do3 Class Array") { point.each { |p| a=p;a==p } } # 赋值+判断自身引用
  17. Test.test("Each_Index Class Array")  { point.each_index { |i| } } # Each_Index迭代
  18. #Test.test("Each_Index2 Class Array") { point.each_index { |i| p==[i,i] } }  # !!卡死
  19. Test.test("For Class Array")  { for i in 0...point.size; end  } # For迭代
结果
RUBY 代码复制
  1. Push Class Array
  2. 2.076804
  3. Include Class Array
  4. 2.170404
  5. Do Class Array
  6. 3.902007
  7. Do2 Class Array
  8. 0.624001
  9. Do3 Class Array
  10. 1.113064
  11. Each_Index Class Array
  12. 0.622035
  13. For Class Array
  14. 0.641037


感觉而言,Include 和 迭代+Ruby实现的判断,差不多。
根据以上测试,include效率低下应该是Array自身的判断==问题。
Array先判断是否是自身引用,然后再判断数组元素。

总而言之,Ruby的Array类是个效率非常低的类= =

点评

所以应该是Array自身的判断==问题。Array先判断是否是自身引用,然后再判断数组元素。  发表于 2015-1-28 15:19
Test.test("Each_Index2 Class Array") { point.each_index { |i| p==[i,i] } } 这一行不要试,因为卡死了。。  发表于 2015-1-28 15:18
其中赋值需要0.1s  发表于 2015-1-28 15:17
Test.test("Do3 Class Array") { point.each { |p| a=p;a==p } } 结果是1.113064  发表于 2015-1-28 15:14
那估计是Array#==太慢了?  发表于 2015-1-28 15:11
RyanBern 发表于 2015-1-28 14:24:57
我的测试结果:

因为机子太慢我改成5000000了TAT

啥?为啥不一样?因为我改了源码。
RUBY 代码复制
  1. class Test
  2.   def self.test(string,&block)
  3.     time = Time.new
  4.     block.call
  5.     puts string,Time.new-time
  6.   end
  7. end
  8.  
  9. class Point
  10.   attr_accessor :x, :y
  11.   def initialize(x, y)
  12.     @x = x
  13.     @y = y
  14.   end
  15.   def ==(point)
  16.     return @x==point.x && @y==point.y
  17.   end
  18. end
  19.  
  20. class Array
  21.   def point_include?(point_arr)
  22.     self.each do |point|
  23.       return true if point[0] == point_arr[0] && point[1] == point_arr[1]
  24.     end
  25.     return false
  26.   end
  27. end
  28.  
  29.  
  30. point1 = Array.new
  31. point2 = Array.new
  32. max = 5000000
  33.  
  34. Test.test("Push Class Point") { max.times { |i| point1.push Point.new(i,i) } }
  35.  
  36. Test.test("Push Class Array") { max.times { |i| point2.push [i,i] } }
  37.  
  38. Test.test("Include Class Point") { point1.include?(Point.new(max,0)) } # 取最坏情况
  39.  
  40. Test.test("Include Class Array") { point2.point_include?([max,0]) }

总觉得Array#==方法太不自然了。

点评

Array也是一个对象  发表于 2015-1-28 15:44
话说Ruby真是想什么就有什么,我只是试着clone一下就成功了  发表于 2015-1-28 15:40
我用Array=Array.clone在类的内部创建了一个副本,这样就不会影响到外面了~  发表于 2015-1-28 15:38
+1,这样改来,还是Array快一点。= =不过还要袭击内部类,真是各种蛋疼。。。  发表于 2015-1-28 14:41

评分

参与人数 2星屑 +190 收起 理由
恐惧剑刃 + 150 认可答案
寒冷魔王 + 40 帅气

查看全部评分

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-5-17 02:30

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表