我正在处理大量数据,并且我担心我的大规模运营效率。基准测试后,执行此代码串的平均时间约为0.004秒。这行代码的目标是找到每个数组位置中两个值之间的差异。在先前的操作中,111.111被加载到包含无效数据的位置的数组中。由于一些奇怪的时域问题,我需要这样做,因为我不能删除值,我需要一些可区分的占位符。我可以使用' nil'在这里。无论如何,回到解释。这行代码检查以确保这两个数组在当前位置都没有此111.111占位符。如果值有效,那么我执行数学运算,否则我想删除这些值(或者至少将它们从我写入的新数组中排除)。我通过放置一个' nil'在那个位置,然后压缩阵列。
每个阵列中4000个数据点的0.004秒时间并不可怕,但这行代码执行了25M次。我希望有人能够提供一些有关我如何优化这一行代码的见解。
temp_row = row_1.zip(row_2).map do |x, y|
x == 111.111 || y == 111.111 ? nil : (x - y).abs
end.compact
答案 0 :(得分:2)
您在三元语句中浪费CPU生成nil
,然后使用compact
删除它们。相反,请使用reject
或select
查找不包含111.111
然后map
或类似内容的元素。
而不是:
row_1 = [1, 111.111, 2]
row_2 = [2, 111.111, 4]
temp_row = row_1.zip(row_2).map do |x, y|
x == 111.111 || y == 111.111 ? nil : (x - y).abs
end.compact
temp_row # => [1, 2]
我从:
开始temp_row = row_1.zip(row_2)
.reject{ |x,y| x == 111.111 || y == 111.111 }
.map{ |x,y| (x - y).abs }
temp_row # => [1, 2]
或者:
temp_row = row_1.zip(row_2)
.each_with_object([]) { |(x,y), ary|
ary << (x - y).abs unless (x == 111.111 || y == 111.111)
}
temp_row # => [1, 2]
对不同大小的数组进行基准测试显示了很多好处:
require 'benchmark'
DECIMAL_SHIFT = 100
DATA_ARRAY = (1 .. 1000).to_a
ROW_1 = (DATA_ARRAY + [111.111]).shuffle
ROW_2 = (DATA_ARRAY.map{ |i| i * 2 } + [111.111]).shuffle
Benchmark.bm(16) do |b|
b.report('ternary:') do
DECIMAL_SHIFT.times do
ROW_1.zip(ROW_2).map do |x, y|
x == 111.111 || y == 111.111 ? nil : (x - y).abs
end.compact
end
end
b.report('reject:') do
DECIMAL_SHIFT.times do
ROW_1.zip(ROW_2).reject{ |x,y| x == 111.111 || y == 111.111 }.map{ |x,y| (x - y).abs }
end
end
b.report('each_with_index:') do
DECIMAL_SHIFT.times do
ROW_1.zip(ROW_2)
.each_with_object([]) { |(x,y), ary|
ary += [(x - y).abs] unless (x == 111.111 || y == 111.111)
}
end
end
end
# >> user system total real
# >> ternary: 0.240000 0.000000 0.240000 ( 0.244476)
# >> reject: 0.060000 0.000000 0.060000 ( 0.058842)
# >> each_with_index: 0.350000 0.000000 0.350000 ( 0.349363)
调整DECIMAL_SHIFT
和DATA_ARRAY
的大小以及111.111
的位置,看看会发生什么情况,以了解哪些表达式最适合您的数据大小和结构以及微调必要的代码。
答案 1 :(得分:0)
您可以尝试parallel
gem https://github.com/grosser/parallel并在多个线程上运行