【问题标题】:How to speed up the process of a simple array iteration?如何加快简单数组迭代的过程?
【发布时间】: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 个副本组成(下面的oorders 的一个元素)。 #1::datetime =&gt; DateTime.parse(o[:date]),9.6 秒。 #2 :datetime =&gt; DateTime.strptime(o[:date], '%Y-%m-%d %H:%M:%S'),1.3 秒。 #3 :datetime =&gt; DateTime.iso8601(t)t = o[:date]; t[10]='T' 之后,3.1 秒。所以只要从parse切换到strptime,你应该可以得到七倍的提升。
  • ..and #4 :datetime =&gt; 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


【解决方案1】:

分析您的代码以查看瓶颈所在。

如果我不得不猜测,Time.zone.parse 可能是 >=80% 的计算进行的地方。给定固定的日期格式,您可以通过手动构造日期对象、从特定范围的子字符串中提取组件来显着提高性能。

【讨论】:

  • 你能告诉我如何改进Time.zone.parse吗?我无法改变 date 作为带有需要设置时区的字符串出现的事实。
  • @ChristofferJoergensen:你错过了关键字“如果我不得不猜测”:)
  • @ChristofferJoergensen,“请您删除答案,所以它看起来没有答案。”?什么?这不是堆栈溢出的工作方式。在您(发布者)将答案标记为“选定”答案之前,该问题看起来不会得到回答。我们不会删除答案以使问题看起来没有答案。
  • 您特别询问了如何加快进程。我们建议您查看代码运行缓慢的最可能原因,并在执行其他操作之前尝试修复它。线程和并行运行最初并没有加快速度,因为它们使工作复杂化,特别是在维护同步它们、不踩公共变量、调试和维护代码时。您没有说您使用的是什么操作系统,但在 *nix 上,创建一个允许多次访问的数据存储,然后启动您的代码的多个实例并让多个实例同时运行。
  • 我使用 orders 运行 OP 的代码,其中包含第一个哈希的 300,000 个副本。花了10.2秒。在注释掉完成解析的行之后(将其更改为:date =&gt; Date.parse(order[:date]) 之后)需要 0.4 秒。看来你的估计差远了。 :-)
猜你喜欢
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
  • 2016-11-21
相关资源
最近更新 更多