在保留空ListProperties或使用动态(expando)属性之间是否存在一些性能问题?

时间:2010-04-05 07:11:51

标签: google-app-engine google-cloud-datastore

在实体需要expando类的动态属性时添加动态属性是否存在数据存储性能差异,或者更简单(对我来说)框架只是设置我可能从一开始就需要的所有可能属性,即使大多数实例都是只是留空。

在我的特定情况下,当我跳过使用expando类时,我将有5-8个空的ReferenceList属性作为“开销”将是空的。

2 个答案:

答案 0 :(得分:1)

从一开始就设置所有可能需要的属性会受到惩罚。

如果您使用常规db.Model,那么每当您放置()时,每个属性都将被序列化。这包括属性名称和值的开销。即使属性的值不是必需的并且设置为None,也会出现此开销! (虽然将值设置为None似乎会导致稍微更小的protobuf表示。)

另一方面,如果您使用db.Expando并且指定可能不会出现的属性,则实际存在的动态属性模型将被序列化。不存在的动态属性根本没有序列化=>没有开销。但是,如果在模型上显式声明(固定)属性,那么您将具有与常规db.Model完全相同的开销(常规模型和expando模型之间的固定属性序列化没有区别)。

在实践中,我不知道使用固定属性的开销是否足以显着影响性能,但它肯定会占用更多的存储空间和CPU时间来序列化甚至空的固定字段。

如果我是你,我会使用expando模型和动态属性。


示例应用,演示了我上面描述的内容:

from google.appengine.ext import db, webapp
from google.appengine.ext.webapp.util import run_wsgi_app

# all model names equal length because they get serialized too
class EmptyModel(db.Model):
    pass

class TestVModel(db.Model):
    value = db.IntegerProperty(required=False)

class TestExpand(db.Expando):
    pass

class MainPage(webapp.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'

        # create an empty model, one with a prop = None, and one with a prop set
        tEmpty = EmptyModel()
        tNone = TestVModel()
        tVal = TestVModel(value=5)

        # do the same but using an expando model with a dynamic property
        eEmpty = TestExpand()
        eNone = TestExpand()
        eNone.value = None
        eVal = TestExpand()
        eVal.value = 5

        # determine the serialized size of each model (note: no keys assigned)
        fEncodedSz = lambda o : len(db.model_to_protobuf(o).Encode())
        szEmpty = fEncodedSz(tEmpty)
        szNone = fEncodedSz(tNone)
        szVal = fEncodedSz(tVal)
        szEEmpty = fEncodedSz(eEmpty)
        szENone = fEncodedSz(eNone)
        szEVal = fEncodedSz(eVal)

        # output the results
        self.response.out.write("Comparison of model sizes with fixed props with expando models\nwith dynamic props:\n\n")
        self.response.out.write("Model:   empty=>%dB  prop=None=>%dB  prop=Val=>%dB\n" %\
                                    (szEmpty, szNone, szVal))
        self.response.out.write("Expando: empty=>%dB  prop=None=>%dB  prop=Val=>%dB\n\n" %\
                                    (szEEmpty, szENone, szEVal))
        self.response.out.write("Note that the expando property which specifies *no* value for the\ndynamic property 'value' is smaller than if 'None' is assigned.")

application = webapp.WSGIApplication([('/', MainPage)])
def main(): run_wsgi_app(application)
if __name__ == '__main__': main()

<强>输出

Comparison of model sizes with fixed props with expando models
with dynamic props:

Model:   empty=>30B  prop=None=>43B  prop=Val=>45B
Expando: empty=>30B  prop=None=>43B  prop=Val=>45B

Note that the expando property which specifies *no* value for the
dynamic property 'value' is smaller than if 'None' is assigned.

答案 1 :(得分:0)

考虑到您可以使用Expando交换Model,我会说它们只是数据存储区实体的客户端外观,而后者又没有固定的架构。因此在数据存储区中既没有模型也没有Expandos,每个对象实例的属性数量并不重要(除了通常的方式之外,即对象越大,传输它所花费的时间就越多) 。 但如果我在这里错了,请减去并纠正我:)