0

ユーザーを選択するためのアルゴリズムを作成しました。これは、無限のスクロールWebページで使用されているため、実行速度が思ったよりも遅くなります。

Rubyについては、効率を改善する方法を特定するのに十分な知識がありません。誰かアイデアはありますか?

def gen_users(list_length)
new_selection = []

# get all users
all_users = User.all

# shuffle them randomly
shuffled_users = all_users.shuffle

# cycle through all users randomly
shuffled_users.each do |user|
    # check user profile isn't already in current selection
    if !@users.include?(user)
    # check user profile exists
    if user.etkh_profile
        profile_completeness = user.etkh_profile.get_profile_completeness

        # check user profile meets minimum requirements        
        if profile_completeness >= MIN_PROFILE_COMPLETENESS && user.avatar? \
        && user.etkh_profile.background.length >= MIN_BACKGROUND_LENGTH

        # insert randomness and bias towards profiles with high completeness
        r = Random.new
        rand = r.rand(1..10)  # random integer between 1 and 10
        product = rand * profile_completeness

        # threshold is defined by the probability that a profile with min profile completeness
        # will be selected

        max_product = MIN_PROFILE_COMPLETENESS * 10
        threshold = (1 - PROBABILITY_MIN_PROFILE) * max_product

        if product >= threshold
            # add to total list
            @users << user

            # add to list of latest selection
            new_selection << user
        end
        end
    end
    end

    # exit loop if enough users have been found
    break if new_selection.length >= list_length
end

# return this selection
return new_selection
end
4

2 に答える 2

3

あなたが間違っている2つのことは次のとおりです。

  • threshold一定です。ループのたびにそれを計算するべきではありません。
  • Random.new再利用する必要があります。それが目的です。ループのたびに新しいインスタンスを作成するべきではありません。

コードのリファクタリング (steenslag の改善が組み込まれています) は次のようになります。

THRESHOLD = (1 - PROBABILITY_MIN_PROFILE) * MIN_PROFILE_COMPLETENESS * 10
RANDOM_GENERATOR = Random.new

def gen_users(list_length)
  (User.all - @users)
  .select do |user|
    profile = user.etkh_profile and
    profile.background.length >= MIN_BACKGROUND_LENGTH and
    (completeness = profile.get_profile_completeness) >= MIN_PROFILE_COMPLETENESS and
    RANDOM_GENERATOR.rand(1..10) * completeness >= THRESHOLD
  end
  .select(&:avatar?)
  .sample(list_length)
  .tap{|a| @users.concat(a)}
end
于 2013-02-24T16:45:13.930 に答える
0

具体的に何がパフォーマンスを低下させるのかを特定するのは非常に困難です。たとえば、ユーザー数によって異なります。また:

  1. max_productthresholdは定数なので、サイクルごとに計算する必要はありません。
  2. たぶんuser.etkh_profile遅い方法ですか?サイクルごとに 3 回呼び出します。
  3. all_usersまた、大量のデータ (と)を持つ 2 つのローカル変数を格納する必要もありませんshuffled_users。代わりに、次のようなことができますshuffled_users = User.all.shuffle
于 2013-02-24T16:56:31.150 に答える