问题描述
|
我知道这是一个模糊的问题。...但是这段代码的性能太糟糕了。从原始帖子到操作到呈现页面大约需要15秒...
此操作的目的是从简历中检索所有职业,该简历中的所有技能以及职业。它们需要按2个数组进行组织:
第一个数组包含所有职业(无重复),并根据得分排序。 Fo每个两次进入均发现分数增加1
第二个数组包含职业数组和简历中的所有技能。再次不允许双打,但是每遇到一个双打,现有分数就会增加一。
下面是执行此操作的代码块。与我的其他代码段相比,它相对较大,但我希望它是可以理解的。我知道像我一样使用数组会令人困惑,但这是每个数组位置的含义:
位置0:实际的技能/职业对象
位置1:条目得分
位置2:在数据库中找到的位置
位置3:在简历中找到的位置
def归类
@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,[],[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,[\'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
我可以发布其他模型和迁移信息,以明确每个类的作用,但是我认为上述脚本的前几行应该在关联上清晰明了。我正在寻找一种优化每个循环的方法...
解决方法
那是相当的代码块。通常,如果您编写的方法很严重,将来将很难维护它。一种有用的技术是将完整的代码块分解成一个帮助器类,以更逻辑的阶段进行处理,从而更轻松地微调代码的各个方面。
例如,接口可能是:
@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
虽然我会特别注意is4ѭ以查看其中的情况,但是很难仅凭它说出为什么它会变慢。可能是初始加载非常缓慢,但其余方法都很好。
,您应该对代码进行概要分析,以查看花费了很多时间。您可以弄清楚如何使用探查器,或者在整个代码中撒一些简单的puts
或logger.info
语句并加上时间戳。使用ѭ7by可能最容易做到这一点。注意:您可能需要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 }}