哪个是最有效的?

时间:2011-07-18 04:17:52

标签: python mod-wsgi fastcgi lighttpd wsgi

问题

其中哪一项最快?

我正在使用lighttpd的mod_fastcgi,Python 2.7和flup.server.fcgi.WSGIServer

我应该直接在some_output_function中产生字符串,然后从app 返回吗?

def app(env, start):
    start('200 OK', [('Content-Type', 'text/html')])
    return some_output_function()

def some_output_function():
    yield function_that_returns_a_string()
    yield 'yada yada'
    yield another_function_that_returns_a_string()

WSGIServer(app).run()

我应该some_output_function返回一个数组,然后从app 返回吗?

def app(env, start):
    start('200 OK', [('Content-Type', 'text/html')])
    return some_output_function()

def some_output_function():
    out = []
    out.append(function_that_returns_a_string())
    out.append('yada yada')
    out.append(another_function_that_returns_a_string())
    return out

WSGIServer(app).run()

我应该some_output_function获得最后一分钟加入的数组,然后从app 返回吗?

def app(env, start):
    start('200 OK', [('Content-Type', 'text/html')])
    return some_output_function()

def some_output_function():
    out = []
    out.append(function_that_returns_a_string())
    out.append('yada yada')
    out.append(another_function_that_returns_a_string())
    yield ''.join(out)

WSGIServer(app).run()

我应该some_output_function返回最后一分钟加入的数组,然后从app 收益?

def app(env, start):
    start('200 OK', [('Content-Type', 'text/html')])
    yield some_output_function()

def some_output_function():
    out = []
    out.append(function_that_returns_a_string())
    out.append('yada yada')
    out.append(another_function_that_returns_a_string())
    return ''.join(out)

WSGIServer(app).run()

测试结果

通过创建一个简单的测试应用程序,输出函数有一个函数调用,然后是十六个'yada yada'字符串,然后另一个函数调用作为输出,我使用ApacheBench收集了一些令人惊讶的平均请求时间。

sudo ab -n10000 -c128 localhost/testapp/
  • 44毫秒直接在some_output_function中生成字符串,然后从app
  • 返回
  • 44毫秒some_output_function返回数组,然后从app
  • 返回
  • 30毫秒some_output_function获得最后一分钟加入的数组,然后从app
  • 返回
  • 30毫秒some_output_function返回最后一分钟加入的数组,然后从app
  • 收益

更有趣的是,当'yada yada'输出字符串的数量增加八倍,到128'yada yada'输出字符串时,这些就是结果:

  • 146毫秒直接在some_output_function中生成字符串,然后从app
  • 返回
  • 146 ms some_output_function返回数组,然后从app
  • 返回
  • 30毫秒some_output_function获得最后一分钟加入的数组,然后从app
  • 返回
  • 30毫秒some_output_function返回最后一分钟加入的数组,然后从app
  • 收益

似乎节省时间的一个共同因素是构建一个字符串数组,然后在退出内部输出函数之前加入它,而不是在任何地方产生。无论你是在内部屈服还是在外面返回,或者在内部返回并在内部屈服,都不会改变任何东西。

所以现在唯一的问题是,我应该在内部还是外部屈服?

2 个答案:

答案 0 :(得分:1)

作为一般规则,在处理大量数据时,生成器比列表更有效。如果元素的数量很小(例如,在您的示例中,只有三个元素),则列表的开销会减少。

无论您选择哪种方法,从缓存或数据存储中获取数据所花费的时间(数十到数百毫秒)都很可能会相形见绌。削减10毫秒的响应时间可能不值得担心。

应该使用生成器的原因不是速度,而是因为大型响应将流式传输到客户端,这将使用更少的内存并释放服务器来处理更多请求。当使用异步服务器(例如,带有eventlet worker,Tornado等的gunicorn)时,这尤其有用。

回答这个问题:

  

所以现在唯一的问题是,我应该在内部还是外部屈服?

实际上它应该没有任何区别。

答案 1 :(得分:1)

生成大量小字符串而不是单个大字符串的速度较慢,因为WSGI规范要求底层WSGI服务器/适配器在写入下一个字符串之前执行每个字符串的刷新。字符串的刷新可以经历多个层,具体取决于最终使用的服务器在套接字上的刷新。正如你多次这样做,写一个更大的字符串会更加昂贵。