Какой из них является наиболее эффективным? - PullRequest
0 голосов
/ 18 июля 2011

Вопрос

Какой из них самый быстрый?

Я использую lighttpd's 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 мс для возврата массива из some_output_function, затем возврата из app
  • 30 мс для получения объединенного массива в последнюю минуту из some_output_function, а затем возвратас app
  • 30 мс для возврата объединенного массива в последнюю минуту из some_output_function, а затем с app

Похоже, чтоОбщим фактором для экономии времени является построение строкового массива, затем соединение с ним непосредственно перед выходом из внутренней выходной функции, а не уступка везде.Если вы уступите внутри и вернетесь наружу или вернетесь внутрь и вернетесь внутрь, то, похоже, ничего не изменится.

Так что единственный вопрос сейчас, действительно, должен ли я уступить внутри или снаружи?

Ответы [ 2 ]

1 голос
/ 18 июля 2011

Создание большого количества маленьких строк по сравнению с одной большой строкой происходит медленнее, поскольку спецификация WSGI требует, чтобы базовый сервер / адаптер WSGI выполнял сброс каждой строки перед записью следующей. Сброс строки может проходить через много слоев в зависимости от используемого сервера, в конечном итоге переходя к очистке сокета. Поскольку вы делаете это много раз, это будет дороже, чем писать одну большую строку.

1 голос
/ 18 июля 2011

Как правило, генераторы более эффективны, чем списки, при работе с большим количеством данных.Список будет меньше накладных расходов, если количество элементов невелико (например, в вашем примере только три элемента).

Какой бы метод вы ни выбрали, он, скорее всего, будет затенен временем, потраченным на выборку данных из кэша.или хранилище данных (от десятков до сотен миллисекунд).Вероятно, не стоит беспокоиться о сокращении времени отклика в 10 мс.

Причина, по которой следует использовать генераторы, заключается не в скорости, а в том, что большие ответы будут передаваться клиенту, который будет использовать меньше памяти и освободит память.сервер для обработки большего количества запросов.Это особенно полезно, когда выполняется с асинхронным сервером (например, gunicorn с работниками eventlet, Tornado и т. Д.).

Чтобы ответить на этот вопрос:

Так что единственный вопрос сейчас, действительноДолжен ли я уступить внутри или снаружи?

Практически это не должно иметь никакого значения.

...