5

我正在 Google App Engine 中开发一个应用程序。我的一种方法是永远不会完成,这让我觉得它陷入了无限循环。我一直盯着它,但无法弄清楚。

免责声明:我使用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 个任何类型的模型。我知道这可能很慢,但我的应用程序只执行一次,然后缓存它。

4

1 回答 1

3

忽略注释掉的递归,我认为这不应该是一个无限循环——你只是在有限的结果集上做一些 for 循环。

但是,看起来这确实很慢。您正在遍历整个表,然后在每个嵌套循环中执行更多数据存储查询。除非您的表非常非常小,否则此类请求似乎不太可能在 GAE 上及时完成。


一些粗略的数字:

If H= # of entity in DepedencyArcHeadand T= average # of tails in each DependencyArcHeadthen:

  • _getListArcTailsWithCourse正在做关于H*T查询(低估)。在“最坏”的情况下,result从这个函数返回的将有H*T元素。
  • _traverseForwards循环所有这些结果H时间,从而执行另一个 H*(H*T) 查询。
  • 即使H并且T仅在 10 秒左右,您也可能会进行数千次查询。如果它们更大,那么......(如果您取消注释递归调用,这将忽略您所做的任何其他查询)。

简而言之,如果可能的话,我认为您可能想尝试以不同的方式组织您的数据。我会提出一个具体的建议,但我不清楚你到底想做什么。

于 2010-06-06T22:40:36.583 回答