Python:deferToThread XMLRPC服务器 - 扭曲 - Cherrypy?

时间:2010-02-04 18:40:16

标签: python multithreading twisted cherrypy

这个问题与我在这里提出的其他问题有关,主要是关于在内存中分类大量数据。

基本上这就是我想要的东西:

Twisted XMLRPC服务器正在运行。该服务器在内存中保留了几(10)个Foo类实例。每个Foo类都包含一个列表栏(包含数百万条记录)。有一项服务从数据库中检索数据,并将其传递给XMLRPC服务器。数据基本上是一个字典,其中的键对应于每个Foo实例,值是一个字典列表,如下所示:

data = {'foo1':[{'k1':'v1', 'k2':'v2'}, {'k1':'v1', 'k2':'v2'}], 'foo2':...}

然后传递每个Foo实例与其键对应的值,并更新和排序Foo.bar词典。

class XMLRPCController(xmlrpc.XMLRPC):

    def __init__(self):
        ...
        self.foos = {'foo1':Foo(), 'foo2':Foo(), 'foo3':Foo()}
        ...

    def update(self, data):
        for k, v in data:
            threads.deferToThread(self.foos[k].processData, v)

    def getData(self, fookey):
        # return first 10 records of specified Foo.bar
        return self.foos[fookey].bar[0:10]

class Foo():

    def __init__(self):
        bar = []

    def processData(self, new_bar_data):
        for record in new_bar_data:
            # do processing, and add record, then sort
            # BUNCH OF PROCESSING CODE
            self.bar.sort(reverse=True)

问题是当在具有大量记录(比如100K +)的XMLRPCController中调用更新函数时,它会停止响应我的getData调用,直到所有32个Foo实例都完成了process_data方法。我认为deferToThread可行,但我认为我误解了问题所在。

任何建议......我愿意使用其他东西,比如Cherrypy,如果它支持这种必要的行为。


修改

@Troy:这就是反应堆的设置方式

reactor.listenTCP(port_no, server.Site(XMLRPCController)
reactor.run()

就GIL而言,改变是否可行 sys.setcheckinterval() 值为较小的值,因此对数据的锁定被释放以便可以读取?

2 个答案:

答案 0 :(得分:1)

让应用程序响应的最简单方法是在较小的块中分解CPU密集型处理,同时让扭曲的反应器在两者之​​间运行。例如,通过调用reactor.callLater(0,process_next_chunk)来前进到下一个块。有效地实施合作多任务处理。

另一种方法是使用单独的流程来完成工作,然后您将受益于多个核心。看看Ampoule:https://launchpad.net/ampoule它提供了类似于deferToThread的API。

答案 1 :(得分:0)

我不知道您的processData方法运行了多长时间,也不知道您是如何设置扭曲反应堆的。 By default,扭曲的反应器有一个0到10个线程的线程池。您可能正在尝试将多达32个长时间运行的计算推迟到多达10个线程。这是次优的。

您还需要询问GIL在更新所有这些集合时扮演的角色。

编辑: 在对程序进行任何重大更改之前(如调用sys.setcheckinterval()),您应该使用探查器或python跟踪模块来运行它。这些应该告诉你使用所有时间的方法。没有正确的信息,您无法做出正确的更改。