5

Google App Engine でアプリを開発しています。私の方法の 1 つは、完了しないことです。これにより、無限ループに陥っていると思われます。私はそれをじっと見つめましたが、それを理解することはできません。

免責事項: http://code.google.com/p/gaeunitリンク テキストを使用してテストを実行しています。挙動がおかしくなったのではないでしょうか?

これは問題のある関数です:

def _traverseForwards(course, c_levels):
    ''' Looks forwards in the dependency graph '''
    result = {'nodes': [], 'arcs': []}

    if c_levels == 0:
        return result

    model_arc_tails_with_course = set(_getListArcTailsWithCourse(course))
    q_arc_heads = DependencyArcHead.all()

    for model_arc_head in q_arc_heads:
        for model_arc_tail in model_arc_tails_with_course:
            if model_arc_tail.key() in model_arc_head.tails:
                result['nodes'].append(model_arc_head.sink)
                result['arcs'].append(_makeArc(course, model_arc_head.sink))

                # rec_result = _traverseForwards(model_arc_head.sink, c_levels - 1)

                # _extendResult(result, rec_result)

    return result

もともと再帰エラーかと思っていたのですが、再帰をコメントアウトして問題が解決しません。この関数を で呼び出すとc_levels = 0、正常に実行されます。

参照するモデル:

class Course(db.Model):
    dept_code = db.StringProperty()
    number = db.IntegerProperty()
    title = db.StringProperty()
    raw_pre_reqs = db.StringProperty(multiline=True)
    original_description = db.StringProperty()

    def getPreReqs(self):
        return pickle.loads(str(self.raw_pre_reqs))

    def __repr__(self):
        return "%s %s: %s" % (self.dept_code, self.number, self.title)

class DependencyArcTail(db.Model):
    ''' A list of courses that is a pre-req for something else '''
    courses = db.ListProperty(db.Key)

    def equals(self, arcTail):
        for this_course in self.courses:
            if not (this_course in arcTail.courses):
                return False

        for other_course in arcTail.courses:
            if not (other_course in self.courses):
                return False

        return True

class DependencyArcHead(db.Model):
    ''' Maintains a course, and a list of tails with that course as their sink '''
    sink = db.ReferenceProperty()
    tails = db.ListProperty(db.Key) 

参照するユーティリティ関数:

def _makeArc(source, sink):
    return {'source': source, 'sink': sink}

def _getListArcTailsWithCourse(course):
    ''' returns a LIST, not SET 
        there may be duplicate entries
    '''
    q_arc_heads = DependencyArcHead.all()
    result = []
    for arc_head in q_arc_heads:
        for key_arc_tail in arc_head.tails:
            model_arc_tail = db.get(key_arc_tail)
            if course.key() in model_arc_tail.courses:
                result.append(model_arc_tail)

    return result

ここでかなり明白な何かが欠けていますか、それとも GAEUnit が動作していますか?

また、この実行を遅くしているテストでは、データストア内にどの種類のモデルも 5 つ以下しかありません。これが遅くなる可能性があることはわかっていますが、私のアプリはこれを 1 回だけ実行し、その後キャッシュします。

4

1 に答える 1

3

コメントアウトされた再帰を無視すると、これは無限ループであるべきではないと思います.有限の結果セットに対してforループを実行しているだけです.

ただし、これは非常に遅くなるようです。テーブル全体をループしてから、ネストされたループごとにさらにデータストア クエリを実行しています。テーブルが非常に小さい場合を除き、この種のリクエストが GAE でタイムリーに完了する可能性は低いようです。


大まかな数字:

H= エンティティの数DepedencyArcHeadおよびT=それぞれのテールの平均数の場合DependencyArcHead:

  • _getListArcTailsWithCourseH*Tクエリについて行っています (過小評価)。「最悪」の場合、resultこの関数から返される にはH*T要素が含まれます。
  • _traverseForwardsこれらすべての結果時間をループしH、別の H*(H*T) クエリを実行します。
  • HTが 10 程度しかない場合でも、何千ものクエリを実行している可能性があります。それらが大きい場合は...(これにより、再帰呼び出しのコメントを外した場合に行う追加のクエリは無視されます)。

要するに、可能であれば、データを少し違った方法で整理したいと思うかもしれません。具体的な提案をしたいのですが、あなたが何をしようとしているのか正確にはわかりません。

于 2010-06-06T22:40:36.583 に答える