在我的应用程序中,对于其中一个处理程序,我需要获取一堆实体并为每个实体执行一个函数。
我拥有所需的所有礼物的钥匙。在获取它们之后,我需要为它们中的每一个执行1或2个实例方法,这会使我的应用程序减慢很多。为100个实体执行此操作需要大约10秒,这是缓慢的方式。
我试图找到一种方法来获取实体并并行执行这些功能以节省时间,但我不确定哪种方式是最好的。
我尝试了_post_get_hook,但我有一个未来的对象,需要调用get_result()并在钩子中执行该函数,这在sdk中运行良好,但在调用Python时会获得大量的超出最大递归深度objec'但我不能真正理解为什么和错误信息不是真的很复杂。
是我正在搜索的管道api或ndb.Tasklets吗?
我试着通过反复试验,但如果有人能引导我走向正确的方向,我会很高兴。修改
我的代码类似于文件系统,每个文件夹都包含其他文件夹和文件。集合的路径在另一个实体上设置,以便序列化集合实体,我需要获取引用的实体并获取路径。在Collection上,serialized_assets()函数越慢,它包含的实体越多。如果我可以并排执行每个包含的资产的序列化功能,它会加快速度。
class Index(ndb.Model):
path = ndb.StringProperty()
class Folder(ndb.Model):
label = ndb.StringProperty()
index = ndb.KeyProperty()
# contents is a list of keys of contaied Folders and Files
contents = ndb.StringProperty(repeated=True)
def serialized_assets(self):
assets = ndb.get_multi(self.contents)
serialized_assets = []
for a in assets:
kind = a._get_kind()
assetdict = a.to_dict()
if kind == 'Collection':
assetdict['path'] = asset.path
# other operations ...
elif kind == 'File':
assetdict['another_prop'] = asset.another_property
# ...
serialized_assets.append(assetdict)
return serialized_assets
@property
def path(self):
return self.index.get().path
class File(ndb.Model):
filename = ndb.StringProperty()
# other properties....
@property
def another_property(self):
# compute something here
return computed_property
EDIT2:
@ndb.tasklet
def serialized_assets(self, keys=None):
assets = yield ndb.get_multi_async(keys)
raise ndb.Return([asset.serialized for asset in assets])
这个tasklet代码好吗?
答案 0 :(得分:2)
由于函数的大部分执行时间都花在等待RPC上,因此NDB的异步和tasklet支持是你最好的选择。这已经详细描述了here。您需求的最简单用法可能是使用ndb.map
函数,如下所示(来自文档):
@ndb.tasklet
def callback(msg):
acct = yield ndb.get_async(msg.author)
raise tasklet.Return('On %s, %s wrote:\n%s' % (msg.when, acct.nick(), msg.body))
qry = Messages.query().order(-Message.when)
outputs = qry.map(callback, limit=20)
for output in outputs:
print output
为查询返回的每个实体调用回调函数,它可以执行所需的任何操作(使用_async
方法和yield
异步执行),并在完成后返回结果。因为回调是一个tasklet,并使用yield来进行异步调用,所以NDB可以并行运行它的多个实例,甚至批处理一些操作。
答案 1 :(得分:0)
管道API对您想要做的事情来说太过分了。你有什么理由不能使用任务队列吗?
使用初始请求获取所有实体密钥,然后为每个具有任务执行每个实体2个功能的密钥排队任务。然后,并发将基于为该任务队列配置的并发请求数。