这是一个我知道的模糊问题......但是这段代码的表现非常糟糕。从原始帖子到渲染页面的操作大约需要15秒......
此操作的目的是从CV中检索所有职业,从该CV和职业中获取所有技能。它们需要组织成两个阵列:
第一个数组包含所有职业(没有重复),并根据他们的分数对它们进行排序。每个双重条目发现得分增加1
第二个数组包含占用数组和cv的所有技能。同样不允许双打,但是对于遇到的每一个双倍,现有的分数增加一个。
以下是执行此操作的代码块。与我的其他代码片段相比,它相对较大,但我希望这是可以理解的。我知道使用像我这样的数组令人困惑,但这是每个数组位置的含义:
位置3:在cv中找到的位置
def defize
@cv = Cv.find(params[:cv_id], :include => [:desired_occupations, :past_occupations, :educational_skills]) @menu = :second @language = Language.resolve(:code => :en, :name => :en) @occupation_hashes = [] @skill_hashes = [] (@cv.desired_occupations + @cv.past_occupations).each do |occupation| section = [] section << 'Desired occupation' if @cv.desired_occupations.include? occupation section << 'Work experience' if @cv.past_occupations.include? occupation unless (array = @occupation_hashes.assoc(occupation)).blank? array[1] += 1 array[2] = (array[2] & section).uniq else @occupation_hashes << [occupation, 1, section] end occupation.skills.each do |skill| unless (array = @skill_hashes.assoc skill).blank? label = occupation.concept.label(@language).value array[1]+= 1 array[3] << label unless array[3].include? label else @skill_hashes << [skill, 1, [], [occupation.concept.label(@language).value]] end end end @cv.educational_skills.each do |skill| unless (array = @skill_hashes.assoc skill).blank? array[1]+= 1 array[3] << 'Education skills' unless array[3].include? 'Education skills' else @skill_hashes << [skill, 1, ['Education skills'], []] end end # Sort the hashes @occupation_hashes.sort! { |x,y| y[1] <=> x[1]} @skill_hashes.sort! { |x,y| y[1] <=> x[1]} @max = @skill_hashes.first[1] @min = @skill_hashes.last[1] end
我可以发布其他模型和迁移,以明确每个类的功能,但我认为上述脚本的前几行应该清楚关联。我正在寻找一种优化每个循环的方法......
答案 0 :(得分:1)
这就是那里的代码块。一般来说,如果您正在编写严谨的方法,那么将来您将难以维护它。一种有助于分解整块代码并将其转换为辅助类的技术,可以在更合理的阶段进行处理,从而更容易对其进行微调。
例如,界面可能是:
@categorizer = CvCategorizer.new(params[:cv_id])
这将封装上述所有内容并将其保存到通过attr_reader
声明可访问的实例变量中。
使用实用程序类意味着您可以将初始化分解为更清晰的步骤:
def initialize(cv_id)
# Call a wrapper method that loads the CV
@cv = self.load_cv(cv_id)
# Perform discrete steps to re-order the imported data
self.organize_occupations
self.organize_skills
end
通过观察它很难说为什么这么慢,尽管我会非常关注log/development.log
来看看那里发生了什么。可能是初始负载很慢,但方法的其余部分都很好。
答案 1 :(得分:1)
您应该对代码进行分析,以查看占用大量时间的内容。您可以弄清楚如何处理分析器,或者在代码中添加一些简单的puts
或logger.info
语句以及时间戳。使用Benchmark
可能最容易做到这一点。注意:您可能需要require 'benchmark'
...不确定是否在Rails中自动需要。
对于单行,您可以执行以下操作:
logger.info Benchmark.measure { @cv = Cv.find(params[:cv_id], :include => [:desired_occupations, :past_occupations, :educational_skills]) }
用于计时更大的代码块:
logger.info Benchmark.measure do
(@cv.desired_occupations + @cv.past_occupations).each do |occupation|
section = []
section << 'Desired occupation' if @cv.desired_occupations.include? occupation
section << 'Work experience' if @cv.past_occupations.include? occupation
unless (array = @occupation_hashes.assoc(occupation)).blank?
array[1] += 1
array[2] = (array[2] & section).uniq
else
@occupation_hashes << [occupation, 1, section]
end
end
end
我只是从大块开始然后缩小它。不知道你要处理的数据集有多大,很难说问题区是什么。
我也会同意其他人的说法,你会把这件事变成更小的方法。这样也可以更轻松地测试性能,因为您可以执行以下操作:
Benchmark.measure { 10000.times { foo.do_that_thing_that_might_be_slow }}