Django REST Framework - медлительность POST, когда размер тела превышает 1024 символа
Я использую DRF. Я обнаружил, что получение POST с более чем 1024 символами приводит к штрафу в ~1 секунду, в то время как все, что меньше этого, эффективно бесплатно. Я упростил это в этом тривиальном примере:
# views.py
import time
from rest_framework.decorators import api_view
from django.http import HttpResponse
@api_view(['POST'])
def test_endpoint(request):
t = time.time()
data = request.body
total_time = time.time() - t
print('got post data:', round(total_time, 3))
return HttpResponse('body size:{} time:{}'.format(len(data), round(total_time, 3)))
# url.py
urlpatterns = [
url(r'^test_endpoint', test_endpoint),
]
Вы можете видеть, что все, что я делаю, это чтение request.body
и измерения времени, которое требуется для этого. Затем я отвечаю с этим временем, и лен request.body
(чтобы доказать, что я получил к нему доступ).
Затем я выполняю эти кудри:
$ time curl -X POST http://127.0.0.1:8000/test_endpoint -d 0123456782345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567901234567890123456789012345678901234567
body size:1024 time:0.0
real 0m0.045s
user 0m0.006s
sys 0m0.009s
$ time curl -X POST http://127.0.0.1:8000/test_endpoint -d 01234567823456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345679012345678901234567890123456789012345678
body size:1025 time:0.999
real 0m1.020s
user 0m0.006s
sys 0m0.006s
Вы можете видеть, что у второго есть один дополнительный символ, и это приводит к штрафу ~1 секунды до готовности. request.body
,
Это почему? Как я могу предотвратить это?
Больше информации
Я сделал это как ваниль, как мог. Я создал новый проект с django-admin startproject helloworld_project .
, Я положил код выше в него. И запустить его локально с python manage.py runserver
, У меня нет веб-сервера перед ним; Я обращаюсь к нему напрямую через браузер. Это все, что я делаю.
Кроме того, я делаю это на Django==1.11
, Эта проблема, кажется, уходит на Django==2.0
, Я не могу легко перейти на 2.0
, Есть ли решение этой проблемы на 1.11
?
1 ответ
Давайте углубимся и посмотрим, где настоящая медлительность.
Эта функция вызывается из свойства тела.
def read(self, *args, **kwargs):
self._read_started = True
try:
import time
t = time.time()
data = self._stream.read(*args, **kwargs) # HERE(!)
total_time = time.time() - t
print('TOTAL TIME: ', total_time)
return data
except IOError as e:
six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2])
Для 1024 символов:TOTAL TIME: 3.123283386230469e-05
Для 1025 символов: TOTAL TIME: 0.991084098815918
Хм... Эта проблема исчезла в Django 2.0, давайте посмотрим на заметки о выпуске:
Запросы и ответы
Веб-сервер runserver поддерживает HTTP 1.1.
HTTP 1.1 поддерживает фрагментированные передачи, а HTTP 1.0 - нет. Я думаю, что это может объяснить медленное поведение.
Есть ли решение этой проблемы на 1.11?
По умолчанию runserver
Я считаю, что ответ - нет. Но вы не будете использовать его в производстве, верно? Любой другой производственный сервер, такой как gunicorn
, uWSGI
поддерживает HTTP 1.1.