【发布时间】:2015-01-14 19:28:23
【问题描述】:
我的数组有 75,000 条记录,如下所示:
orders = [{ :order_id=>"7617",
:date=>"2014-11-17 19:24:31",
:firstname=>"Jack",
:lastname=>"Bauer"},
{ :order_id=>"7618",
:date=>"2014-11-17 19:34:51",
:firstname=>"James",
:lastname=>"Bond"},
... ]
我现在需要使用以下代码遍历这个数组:
order_id_array = []
order_array = []
orders.each do |order|
prepared_order = prepare_order(order)
order_id_array << prepared_order[0]
order_array << prepared_order[1]
end
def prepare_order(order)
order_id = order[:order_id]
[ order_id,
{ :order_id => order_id,
:name => "#{order[:firstname]} #{order[:lastname]}",
:date => Time.zone.parse(order[:date]),
:customer_id => Moped::BSON::ObjectId.new } ]
end
这个过程大约需要 15 秒。这太过分了。有时我的数组包含 5M+ 哈希。
如何加快这个过程?
我曾尝试像这样使用parallel gem:
Parallel.each(orders, :in_threads => 3){ |order|
...
}
但是,这对我没有任何作用。
【问题讨论】:
-
“我如何加快这个过程”——第一步是找出慢的部分。
-
我一直在寻找一种更基本的加速方法。我在这里没有做太多繁重的计算,所以即使我例如花费时间解析我仍然会处于必须逐个迭代它们的情况。
-
顺便说一句,你试过在 MRI 上穿线吗?馊主意。试试 JRuby 或 Rubinius,它可能会产生更好的结果。
-
从我之前在@Mattt 的回答上发表的评论中,很明显日期时间转换是瓶颈。我运行了三个案例,每个案例都有
orders,由第一个哈希的300,000 个副本组成(下面的o是orders的一个元素)。 #1::datetime => DateTime.parse(o[:date]),9.6 秒。 #2:datetime => DateTime.strptime(o[:date], '%Y-%m-%d %H:%M:%S'),1.3 秒。 #3:datetime => DateTime.iso8601(t)在t = o[:date]; t[10]='T'之后,3.1 秒。所以只要从parse切换到strptime,你应该可以得到七倍的提升。 -
..and #4
:datetime => DateTime.new(s[0,4].to_i, s[5,2].to_i, s[8,2].to_i, s[11,2].to_i, s[14,2].to_i, s[17,2].to_i )(其中s=o[:date]),1.1 秒。考虑到strptime是用C 编写的,我预计它会比使用new快一点,但是事实并非如此。
标签: ruby arrays multithreading performance