<p>الطلبات ذات أداء ضعيف لدفق استجابات ثنائية كبيرة</p>

تم إنشاؤها على ٥ ديسمبر ٢٠١٤  ·  40تعليقات  ·  مصدر: psf/requests

يحتوي https://github.com/alex/http-client-bench على المعايير التي استخدمتها.

النتائج مثل:

| | طلبات / http | مقبس |
| --- | --- | --- |
| CPython | 12 ميغا بايت / ثانية | 200 ميغا بايت / ثانية |
| PyPy | 80 ميغا بايت / ثانية | 300 ميغا بايت / ثانية |
| اذهب | 150 ميغا بايت / ثانية | غير متوفر |

تفرض الطلبات مقدارًا كبيرًا مقارنة بالمقبس ، خاصة على جهاز CPython.

Propose Close

ال 40 كومينتر

هذا الحمل كبير بشكل غير متوقع. ومع ذلك ، قد يكون تجنبه أمرًا صعبًا.

المشكلة الكبرى هي أننا نقوم بمعالجة الكثير لكل قطعة. هذا هو كل الطريق أسفل المكدس: الطلبات ، urllib3 و HTplib. سيكون من المثير للاهتمام للغاية معرفة أين يتم قضاء الوقت في معرفة من الذي يسبب عدم الكفاءة.

تخمين أن الخطوة التالية ستكون تجربة التنميط HTplib / urllib3 لرؤية ملف
الأداء هناك؟

كيفن بيرك
الهاتف: 925.271.7005 | twentymilliseconds.com

يوم الخميس ، 4 ديسمبر 2014 الساعة 5:01 مساءً ، كوري بنفيلد [email protected]
كتب:

هذا الحمل كبير بشكل غير متوقع. ومع ذلك ، قد يكون تجنبه أمرًا صعبًا.

المشكلة الكبرى هي أننا نقوم بمعالجة الكثير لكل قطعة. هذا
على طول الطريق إلى أسفل المكدس: الطلبات و urllib3 و HTplib. سيكون من
من المثير للاهتمام للغاية معرفة المكان الذي يقضيه الوقت في معرفة من
يسبب عدم الكفاءة.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65732050
.

نفذت للتو معايير مع urllib3:

PyPy: 120 ميغا بايت / ثانية
CPython: 70 ميغا بايت / ثانية

وأعدت تشغيل طلبات CPython +: 35 ميجابايت / ثانية

(يبدو أن جهازي يعاني من قدر كبير من الضوضاء في المعايير ، إذا كان لدى أي شخص نظام أكثر هدوءًا يمكنه تشغيله ، فسيكون ذلك رائعًا)

حاولت تشغيل هذه على جهازي بعد إغلاق بعضها البعض
التطبيق ونافذة المحطة وحصلت على قدر لا بأس به من الضوضاء أيضًا -
كان معيار المقبس في أي مكان من 30 ميجابايت / ثانية إلى 460 ميجابايت / ثانية.

كيفن بيرك
الهاتف: 925.271.7005 | twentymilliseconds.com

يوم الخميس ، 4 ديسمبر 2014 الساعة 9:24 مساءً ، أليكس جاينور إخطارات @github.com
كتب:

نفذت للتو معايير مع urllib3:

PyPy: 120 ميغا بايت / ثانية
CPython: 70 ميغا بايت / ثانية

وأعدت تشغيل طلبات CPython +: 35 ميجابايت / ثانية

(يبدو أن جهازي يعاني من قدر كبير من الضوضاء في المعايير ، إذا كان
أي شخص لديه نظام أكثر هدوءًا يمكنه تشغيله ، وسيكون ذلك رائعًا)

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65748982
.

لقد جعلت تشغيل المعايير أسهل الآن ، لذا آمل أن يتحقق الأشخاص الآخرون من أرقامي:

CPython:

BENCH SOCKET:
   8GiB 0:00:22 [ 360MiB/s] [======================================================>] 100%
BENCH HTTPLIB:
   8GiB 0:02:34 [53.1MiB/s] [======================================================>] 100%
BENCH URLLIB3:
   8GiB 0:01:30 [90.2MiB/s] [======================================================>] 100%
BENCH REQUESTS
   8GiB 0:01:30 [90.7MiB/s] [======================================================>] 100%
BENCH GO HTTP
   8GiB 0:00:26 [ 305MiB/s] [======================================================>] 100%

PyPy:

BENCH SOCKET:
   8GiB 0:00:22 [ 357MiB/s] [======================================================>] 100%
BENCH HTTPLIB:
   8GiB 0:00:43 [ 189MiB/s] [======================================================>] 100%
BENCH URLLIB3:
   8GiB 0:01:07 [ 121MiB/s] [======================================================>] 100%
BENCH REQUESTS
   8GiB 0:01:09 [ 117MiB/s] [======================================================>] 100%
BENCH GO HTTP
   8GiB 0:00:26 [ 307MiB/s] [======================================================>] 100%

أه .. تلك الأرقام غريبة. يعد برنامج HTplib الخاص بـ CPython أبطأ من الطلبات أو urllib3 ، على الرغم من أن المكتبتين تستخدمان HTplib؟ هذا فقط لا يمكن أن يكون صحيحًا.

إنهم يتكاثرون باستمرار بالنسبة لي - هل يمكنك تجربة المعايير ومعرفة ما إذا كان
يمكنك التكاثر؟ بافتراض أنك تستطيع ، هل ترى أي شيء خاطئ في
المعايير؟

يوم الجمعة 5 ديسمبر 2014 الساعة 11:16:45 صباحًا كوري بنفيلد [email protected]
كتب:

أه .. تلك الأرقام غريبة. يعد HTplib من CPython أبطأ من الطلبات أو
urllib3 ، على الرغم من استخدام كلتا المكتبتين ل htplib؟ هذا فقط لا يمكن أن يكون صحيحًا.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65821989
.

أنا فقط أمسك بآلة هادئة معروفة الآن. يجب أن يستغرق الأمر بضع دقائق حتى يصبح متاحًا لأنه صندوق مادي يجب تثبيته (يا إلهي أحب MAAS).

CPython 2.7.8

BENCH SOCKET:
   8GiB 0:00:26 [ 309MiB/s] [================================>] 100%
BENCH HTTPLIB:
   8GiB 0:02:24 [56.5MiB/s] [================================>] 100%
BENCH URLLIB3:
   8GiB 0:01:42 [79.7MiB/s] [================================>] 100%
BENCH REQUESTS
   8GiB 0:01:45 [77.9MiB/s] [================================>] 100%
BENCH GO HTTP
   8GiB 0:00:27 [ 297MiB/s] [================================>] 100%

لما يستحق:

هذا التصحيح ، CPython 3.4.2 :

BENCH SOCKET:
   8GiB 0:00:27 [ 302MiB/s] [================================>] 100%
BENCH HTTPLIB:
   8GiB 0:00:53 [ 151MiB/s] [================================>] 100%
BENCH URLLIB3:
   8GiB 0:00:54 [ 149MiB/s] [================================>] 100%
BENCH REQUESTS
   8GiB 0:00:56 [ 144MiB/s] [================================>] 100%
BENCH GO HTTP
   8GiB 0:00:31 [ 256MiB/s] [================================>] 100%

يجب أن تكون قادرًا على الحصول على نفس التأثير على Python2 باستخدام
env PYTHONUNBUFFERED= أو العلم -u .

يوم الجمعة 5 ديسمبر 2014 الساعة 11:42:36 صباحًا Corey Farwell [email protected]
كتب:

لما يستحق:

هذا التصحيح https://gist.github.com/frewsxcv/1c0f3c81cda508e1bca9 ، CPython
3.4.2:

مقعد المقعد:
8 جيجا بايت 0:00:27 [302 ميجا بايت / ثانية] [=================================>] 100٪
مقعد HTTPLIB:
8 جيجا بايت 0:00:53 [151 ميجا بايت / ثانية] [=================================>] 100٪
مقعد URLLIB3:
8 جيجا بايت 0:00:54 [149 ميجا بايت / ثانية] [=================================>] 100٪
طلبات البدلاء
8 جيجا بايت 0:00:56 [144 ميجا بايت / ثانية] [=================================>] 100٪
BenCH GO HTTP
8 جيجا بايت 0:00:31 [256 ميجا بايت / ثانية] [================================>] 100٪

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65826239
.

alex ومن المثير للاهتمام ، أن أيا من env PYTHONUNBUFFERED= أو -u لهما نفس التأثير على Python 2. النتائج من الجهاز الوارد الخاص بي.

حسنًا ، تأتي البيانات أدناه من جهاز لا يفعل شيئًا سوى إجراء هذه الاختبارات. تم إجراء الاختبار الأخير باستخدام مجموعة علامات Python -u ، وكما ترى فإن هذه العلامة ليس لها أي تأثير.

Python 2.7.6
go version go1.2.1 linux/amd64
BENCH SOCKET:
   8GiB 0:00:16 [ 500MiB/s] [================================>] 100%
BENCH HTTPLIB:
   8GiB 0:01:32 [88.6MiB/s] [================================>] 100%
BENCH URLLIB3:
   8GiB 0:01:20 [ 101MiB/s] [================================>] 100%
BENCH REQUESTS
   8GiB 0:01:21 [ 100MiB/s] [================================>] 100%
BENCH GO HTTP
   8GiB 0:00:21 [ 385MiB/s] [================================>] 100%
Python 2.7.6
go version go1.2.1 linux/amd64
BENCH SOCKET:
   8GiB 0:00:16 [ 503MiB/s] [================================>] 100%
BENCH HTTPLIB:
   8GiB 0:01:33 [87.8MiB/s] [================================>] 100%
BENCH URLLIB3:
   8GiB 0:01:20 [ 101MiB/s] [================================>] 100%
BENCH REQUESTS
   8GiB 0:01:22 [99.3MiB/s] [================================>] 100%
BENCH GO HTTP
   8GiB 0:00:20 [ 391MiB/s] [================================>] 100%
Python 2.7.6
go version go1.2.1 linux/amd64
BENCH SOCKET:
   8GiB 0:00:16 [ 506MiB/s] [================================>] 100%
BENCH HTTPLIB:
   8GiB 0:01:31 [89.1MiB/s] [================================>] 100%
BENCH URLLIB3:
   8GiB 0:01:20 [ 101MiB/s] [================================>] 100%
BENCH REQUESTS
   8GiB 0:01:20 [ 101MiB/s] [================================>] 100%
BENCH GO HTTP
   8GiB 0:00:21 [ 389MiB/s] [================================>] 100%

هذه الأرقام ثابتة للغاية ، وتظهر الميزات التالية:

  1. قراءات المقبس الخام سريعة (duh).
  2. Go حوالي 80٪ من سرعة قراءة المقبس الخام.
  3. تبلغ سرعة urllib3 حوالي 20٪ من سرعة قراءة المقبس الخام.
  4. الطلبات أبطأ قليلاً من urllib3 ، وهو أمر منطقي لأننا نضيف بضع إطارات مكدسة للبيانات لتمريرها.
  5. HTplib أبطأ من الطلبات / urllib3. هذا مستحيل فقط ، وأظن أننا يجب أن نقوم بتكوين HTplib أو مكتبة المآخذ بطريقة لا يتم تكوينها في الموقع.

FWIW ، لقد دمجت للتو إضافة buffering=True من kevinburke ، قم
تشمل ذلك؟

يوم الجمعة 5 ديسمبر 2014 الساعة 12:04:40 مساءً Cory Benfield [email protected]
كتب:

حسنًا ، تأتي البيانات أدناه من جهاز لا يقوم بأي شيء آخر
لكن إجراء هذه الاختبارات. تم إجراء الاختبار الأخير بعلامة Python -u
مجموعة ، وكما ترى فإن هذا العلم ليس له أي تأثير.

بايثون 2.7.6
انتقل إلى الإصدار go1.2.1 linux / amd64
مقعد المقعد:
8 جيجا بايت 0:00:16 [500 ميجا بايت / ثانية] [=================================>] 100٪
مقعد HTTPLIB:
8 جيجا بايت 0:01:32 [88.6 ميجا بايت / ثانية] [=================================>] 100٪
مقعد URLLIB3:
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
طلبات البدلاء
8 جيجا بايت 0:01:21 [100 ميجا بايت / ثانية] [=================================>] 100٪
BenCH GO HTTP
8 جيجا بايت 0:00:21 [385 ميجا بايت / ثانية] [=================================>] 100٪

بايثون 2.7.6
انتقل إلى الإصدار go1.2.1 linux / amd64
مقعد المقعد:
8 جيجا بايت 0:00:16 [503 ميجا بايت / ثانية] [=================================>] 100٪
مقعد HTTPLIB:
8 جيجا بايت 0:01:33 [87.8 ميجا بايت / ثانية] [=================================>] 100٪
مقعد URLLIB3:
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
طلبات البدلاء
8 جيجا بايت 0:01:22 [99.3 ميجا بايت / ثانية] [=================================>] 100٪
BenCH GO HTTP
8 جيجا بايت 0:00:20 [391 ميجا بايت / ثانية] [=================================>] 100٪

بايثون 2.7.6
انتقل إلى الإصدار go1.2.1 linux / amd64
مقعد المقعد:
8 جيجا بايت 0:00:16 [506 ميجا بايت / ثانية] [=================================>] 100٪
مقعد HTTPLIB:
8 جيجا بايت 0:01:31 [89.1 ميجا بايت / ثانية] [=================================>] 100٪
مقعد URLLIB3:
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
طلبات البدلاء
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
BenCH GO HTTP
8 جيجا بايت 0:00:21 [389 ميجا بايت / ثانية] [=================================>] 100٪

هذه الأرقام ثابتة للغاية ، وتظهر الميزات التالية:

  1. قراءات المقبس الخام سريعة (duh).
  2. Go حوالي 80٪ من سرعة قراءة المقبس الخام.
  3. تبلغ سرعة urllib3 حوالي 20٪ من سرعة قراءة المقبس الخام.
  4. الطلبات أبطأ قليلاً من urllib3 ، وهو أمر منطقي مثلنا
    أضف زوجًا من إطارات المكدس للبيانات لتمريرها.
  5. HTplib أبطأ من الطلبات / urllib3. هذا مستحيل فقط ،
    وأظن أننا يجب أن نقوم بتكوين HTplib أو مكتبة المآخذ في
    بطريقة لا توجد بها htplib.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65829335
.

كوري - اطلع على أحدث إصدار من عميل مقاعد البدلاء الذي يعمل على
التخزين المؤقت = صحيح في HTplib (كما تفعل الطلبات / urllib3)

كيفن بيرك
الهاتف: 925.271.7005 | twentymilliseconds.com

يوم الجمعة ، 5 ديسمبر 2014 ، الساعة 10:04 صباحًا ، Cory Benfield [email protected]
كتب:

حسنًا ، تأتي البيانات أدناه من جهاز لا يقوم بأي شيء آخر
لكن إجراء هذه الاختبارات. تم إجراء الاختبار الأخير بعلامة Python -u
مجموعة ، وكما ترى فإن هذا العلم ليس له أي تأثير.

بايثون 2.7.6
انتقل إلى الإصدار go1.2.1 linux / amd64
مقعد المقعد:
8 جيجا بايت 0:00:16 [500 ميجا بايت / ثانية] [=================================>] 100٪
مقعد HTTPLIB:
8 جيجا بايت 0:01:32 [88.6 ميجا بايت / ثانية] [=================================>] 100٪
مقعد URLLIB3:
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
طلبات البدلاء
8 جيجا بايت 0:01:21 [100 ميجا بايت / ثانية] [=================================>] 100٪
BenCH GO HTTP
8 جيجا بايت 0:00:21 [385 ميجا بايت / ثانية] [=================================>] 100٪

بايثون 2.7.6
انتقل إلى الإصدار go1.2.1 linux / amd64
مقعد المقعد:
8 جيجا بايت 0:00:16 [503 ميجا بايت / ثانية] [=================================>] 100٪
مقعد HTTPLIB:
8 جيجا بايت 0:01:33 [87.8 ميجا بايت / ثانية] [=================================>] 100٪
مقعد URLLIB3:
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
طلبات البدلاء
8 جيجا بايت 0:01:22 [99.3 ميجا بايت / ثانية] [=================================>] 100٪
BenCH GO HTTP
8 جيجا بايت 0:00:20 [391 ميجا بايت / ثانية] [=================================>] 100٪

بايثون 2.7.6
انتقل إلى الإصدار go1.2.1 linux / amd64
مقعد المقعد:
8 جيجا بايت 0:00:16 [506 ميجا بايت / ثانية] [=================================>] 100٪
مقعد HTTPLIB:
8 جيجا بايت 0:01:31 [89.1 ميجا بايت / ثانية] [=================================>] 100٪
مقعد URLLIB3:
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
طلبات البدلاء
8 جيجا بايت 0:01:20 [101 ميجا بايت / ثانية] [=================================>] 100٪
BenCH GO HTTP
8 جيجا بايت 0:00:21 [389 ميجا بايت / ثانية] [=================================>] 100٪

هذه الأرقام ثابتة للغاية ، وتظهر الميزات التالية:

  1. قراءات المقبس الخام سريعة (duh).
  2. Go حوالي 80٪ من سرعة قراءة المقبس الخام.
  3. تبلغ سرعة urllib3 حوالي 20٪ من سرعة قراءة المقبس الخام.
  4. الطلبات أبطأ قليلاً من urllib3 ، وهو أمر منطقي مثلنا
    أضف زوجًا من إطارات المكدس للبيانات لتمريرها.
  5. HTplib أبطأ من الطلبات / urllib3. هذا مستحيل فقط ،
    وأظن أننا يجب أن نقوم بتكوين HTplib أو مكتبة المآخذ في
    بطريقة لا توجد بها htplib.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65829335
.

نعم ، هذا يعمل على إصلاح سلوك أداء HTplib ليكون أكثر منطقية.

نتائج واستنتاجات جديدة:

Python 2.7.6
go version go1.2.1 linux/amd64
BENCH SOCKET:
   8GiB 0:00:16 [ 499MiB/s] [================================>] 100%
BENCH HTTPLIB:
   8GiB 0:01:12 [ 113MiB/s] [================================>] 100%
BENCH URLLIB3:
   8GiB 0:01:21 [ 100MiB/s] [================================>] 100%
BENCH REQUESTS
   8GiB 0:01:20 [ 101MiB/s] [================================>] 100%
BENCH GO HTTP
   8GiB 0:00:20 [ 391MiB/s] [================================>] 100%
  1. قراءات المقبس الخام سريعة (duh).
  2. Go حوالي 80٪ من سرعة قراءة المقبس الخام.
  3. HTplib أقل بقليل من 25٪ من سرعة قراءة المقبس الخام.
  4. تبلغ سرعة urllib3 حوالي 20٪ من سرعة قراءة المقبس الخام ، مما يؤدي إلى إضافة بعض النفقات العامة الصغيرة إلى htplib.
  5. الطلبات أبطأ قليلاً من urllib3 ، وهو أمر منطقي لأننا نضيف بضع إطارات مكدسة للبيانات لتمريرها.

لذا ، يمكن القول إن التكلفة الحقيقية هنا هي HTplib. يتطلب تسريع هذا الأمر التخلص من الموقع.

أنا مهتم بمعرفة أي جزء من HTplib يكلفنا. أعتقد أن تحديد سمات bench_httplib.py خطوة تالية جيدة.

لقد استبعدت تحويل المقبس إلى كائن ملف من خلال socket.makefile عن طريق إضافة هذا السطر إلى اختبار bench_socket.py ، وهذا لا يبطئه على الإطلاق. بغرابة ، يبدو أنه يجعله أسرع.

الجواب يكاد يكون مؤكدًا هو ترميز النقل: المعالجة المقطوعة.
انظر: https://github.com/alex/http-client-bench/pull/6 ، والتبديل إلى
ينتج عن طول المحتوى على الخادم بعض النتائج غير المتوقعة.

يوم الجمعة 5 ديسمبر 2014 الساعة 12:24:53 مساءً Cory Benfield [email protected]
كتب:

لذا ، يمكن القول إن التكلفة الحقيقية هنا هي HTplib. يتطلب تسريع هذا الأمر
الحصول على HTplib بعيدا عن الطريق.

أنا مهتم بمعرفة أي جزء من HTplib يكلفنا. أنا
أعتقد أن إنشاء ملف تعريف bench_httplib.py هو خطوة تالية جيدة.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65831653
.

مثير للإعجاب.

يكاد يكون من المؤكد أن المعالجة المقطوعة هي المشكلة ، ولست مندهشًا حقًا من أن go يتعامل معها بشكل أفضل ، خاصة وأن chunked هو وضع HTTP الافتراضي.

ومع ذلك ، فإن الطلبات التي تكون أسرع من المقبس الخام ... غير متوقعة!

هناك شيء واحد جدير بالملاحظة: إذا لم يكن المقبس يفك تشفير الترميز المقسم في الاختبارات السابقة ، فإنه يتمتع بميزة غير عادلة ، حيث كان يقرأ في الواقع بيانات أقل من الطرق الأخرى! كانوا جميعًا يقرؤون الرؤوس المقسمة بالإضافة إلى 8 جيجابايت من البيانات.

يؤدي هذا إلى سؤال متابعة: هل ما زلنا نعتقد أن كل هذه الأساليب تقرأ بالفعل نفس الكمية من البيانات؟

نعم ، كانت طبقة المقبس غشًا ، ولم تقم بفك تشفير البيانات الوصفية المقسمة ،
وتقنيًا قراءة أقل قليلاً. كان هناك كخط أساسي "لمدى السرعة
هل يمكننا أن نقرأ "، لا لإثبات أي شيء.

يوم الجمعة 5 ديسمبر 2014 الساعة 12:33:10 مساءً Cory Benfield [email protected]
كتب:

مثير للإعجاب.

من المؤكد تقريبًا أن المعالجة المتقطعة هي المشكلة ، وأنا لست كذلك حقًا
مندهشًا من أن go يتعامل معه بشكل أفضل ، خاصة وأن المقسم هو الافتراضي
وضع HTTP للذهاب.

ومع ذلك ، فإن الطلبات التي تكون أسرع من المقبس الخام ... غير متوقعة!

هناك شيء واحد جدير بالملاحظة: إذا لم يكن المقبس يفك تشفير الترميز المقسم
في الاختبارات السابقة ، حصلت على ميزة غير عادلة ، كما كانت بالفعل
قراءة بيانات أقل من الطرق الأخرى! كانوا جميعًا يقرؤون
رؤوس مقسمة بالإضافة إلى 8 غيغابايت من البيانات.

هذا يقودنا إلى سؤال متابعة: هل ما زلنا نفكر في كل هذه الأساليب
تقرأ في الواقع نفس القدر من البيانات؟

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65833299
.

لن أتفاجأ إذا كان هذا مرتبطًا بحجم القطعة التي نقرأها من المقبس في كل مرة.

كعكة alex لكونها مفيدة للغاية: كعكة:

nelhage قام ببعض التمحيص في الأمثلة المختلفة (في عملية النقل
الترميز: حالة مقطعة) https://gist.github.com/nelhage/dd6490fbc5cfb815f762
هي النتائج. يبدو أن هناك خطأ في HTplib والذي ينتج عنه
لا تقرأ دائمًا جزءًا كاملًا من المقبس.

في يوم الإثنين 8 ديسمبر 2014 الساعة 9:05:14 صباحًا ، Kenneth Reitz [email protected]
كتب:

كعكة لـ alex https://github.com/alex لكونها مفيدة للغاية [الصورة:
:كيك:]

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -66147998
.

إذن ما لدينا هنا هو خطأ في مكتبة قياسية لا يقوم أحد بصيانتها حقًا؟ (لدى Lukasa مجموعتان من التصحيحات على الأقل تم سأثير رائحة كريهة في قائمة ما الليلة

ربما يحتاج شخص ما (قد أحصل عليه ، غير واضح) إلى التعمق باستخدام pdb
أو شيء من هذا القبيل واكتشف الشفرة الدقيقة التي تولد تلك الـ 20 بايت
يقرأ حتى نتمكن من إعداد تقرير خطأ جيد.

في يوم الإثنين 8 ديسمبر 2014 الساعة 9:14:09 صباحًا إيان كورداسكو إخطارات github.com
كتب:

إذن ما لدينا هنا هو خطأ في مكتبة قياسية لا يوجد أحد موجود بالفعل
المحافظة؟ ( Lukasa https://github.com/Lukasa به 2 تصحيح على الأقل
المجموعات التي تم فتحها منذ> سنة واحدة.) ربما سأثير رائحة كريهة في القائمة
في مكان ما الليلة

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/2371#issuecomment -66149522
.

سأحاول ملاءمة ذلك الليلة أو غدًا إذا لم يتمكن أحد آخر من الوصول إليه.

إذن ، أي أخبار عن السبب الجذري؟ ما الذي يولد هذه القراءات القصيرة ، وما مدى تحسن الوضع بدونها؟

kislyuk ليس على حد

شكرا @ لوكاسا. أنا أتعامل مع مشكلة في الأداء حيث تكون سرعة التنزيل على استجابة مقسمة باستخدام urllib3 /طلبات أبطأ بكثير من curl والمكتبات الأخرى ، وأحاول فهم ما إذا كان هذا هو الجاني.

كنت أتجول مع هذا قليلاً. تأتي القراءات القصيرة من وظيفة _read_chunked في htplib

https://fossies.org/linux/misc/Python-2.7.9.tgz/Python-2.7.9/Lib/httplib.py#l_585

يبدو أن قراءات 2 بايت تأتي بشكل أساسي من السطر 622.

حصلت على نمط دعامة مختلف قليلاً عن النمط المنشور سابقًا:
الاستلام من (3، "400 \ r \ n \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 "...، 8192، 0، NULL، NULL) = 8192
الاسترداد من (3، "\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 "... ، 54 ، 0 ، NULL ، NULL) = 54
recvfrom (3، "\ r \ n"، 2، 0، NULL، NULL) = 2

يمكن تفسير هذا النمط على النحو التالي:

  • يؤدي سطر self.fp.readline (السطر 591) إلى تشغيل قراءة مخزنة لـ 8192 بايت (في socket.readline)
  • كل قطعة يتم استهلاكها هي 1031 بايت (طول القطعة 5 بايت ("400 \ r \ n") + 1024 بايت من البيانات + 2 بايت من النهاية)
  • يمكننا استهلاك 7 من هذه القطع من 8192 بايت المخزنة مما يترك لنا 975 بايت
  • ثم نقرأ طول المقطع التالي (5 بايت) الذي يترك 970 بايت
  • لدينا الآن 970 بايت فقط وهي غير كافية لتلبية الجزء الحالي (1024) لذلك نعود إلى الشبكة لنقص 54 بايت
  • لإنجاز هذا الموقع ، يقوم بعمل sock.read (54) على وحدات البايت المعلقة. socket.read في هذه الحالة (بطول صريح) سيختار الانتقال إلى الشبكة لـ 54 بايت المحدد (بدلاً من التخزين المؤقت 8192 أخرى)
  • نصل بعد ذلك إلى قراءة فاصل القطعة وهو 2 بايت ومرة ​​أخرى هذا هو نفس السيناريو أعلاه

سيتكرر النمط بعد ذلك (ارجع إلى الخطوة 1)

FWIW ، لقد وجدت أنه يمكن إجراء تسريع متواضع (20٪ أو نحو ذلك) هنا عن طريق لف فاصل المقطع 2 بايت الذي تم قراءته في الجزء الذي تم قراءته ، أي بدلاً من هذا:

            value.append(self._safe_read(chunk_left)) 
            amt -= chunk_left

        self._safe_read(2)  # toss the CRLF at the end of the chunk

افعل هذا بدلاً من ذلك:

            value.append(self._safe_read(chunk_left + 2)[:-2]) 
            amt -= chunk_left

حقًا ، على الرغم من ذلك ، سيكون من الأفضل على الأرجح إذا كانت قراءة 54 بايت يمكن أن تخزن عددًا أكبر من البايتات من 54 (أي 8192 بايت) مما يعني أن المقبس المخزن لن يكون فارغًا عندما يتعلق الأمر بقراءة 2 بايت.

وبالإضافة إلى ذلك. لست متأكدًا من أن القراءات الصغيرة هي العامل الرئيسي في فقدان الإنتاجية (أو ليس على المضيف المحلي). لقد لعبت مع حجم المخزن المؤقت للمقبس بحيث كان مضاعفًا لـ 1031 بايت وعلى الرغم من أن الدعامة لم تعد تحتوي على قراءات صغيرة ، لم يكن لها تأثير كبير على الإنتاجية.

أعتقد أن فقدان الإنتاجية قد يكون متعلقًا بكيفية تعامل socket.py مع القراءات الصغيرة. إليك الكود ذي الصلة (من socket.read):

https://fossies.org/linux/misc/Python-2.7.9.tgz/Python-2.7.9/Lib/socket.py#l_336

عندما تمرر طولًا صريحًا إلى socket.read ويمكن تنفيذه من البيانات المخزنة الموجودة ، فهذا هو مسار الكود:

        buf = self._rbuf
        buf.seek(0, 2)  # seek end

        #.....

        # Read until size bytes or EOF seen, whichever comes first
        buf_len = buf.tell()
        if buf_len >= size:
            # Already have size bytes in our buffer?  Extract and return.
            buf.seek(0)
            rv = buf.read(size)
            self._rbuf = StringIO()
            self._rbuf.write(buf.read())
            return rv

المشكلة التي أراها هنا هي أنه حتى قراءة 2 بايت تعني نسخ الباقي غير المقروء إلى StringIO جديد. يبدو أن هذا سيصبح مكلفًا جدًا للعديد من القراءات الصغيرة. إذا كان من الممكن استنزاف StringIO معين بطريقة ما في كل قراءة بدلاً من النمط الحالي لنسخ الباقي غير المقروء في StringIO جديد ، فأنا أتوقع أن ذلك قد يساعد في الإنتاجية

gardenia لم تتح لي الفرصة لاستيعاب كل هذا ، لكن شكراً جزيلاً @ shazow ربما تجد بحث gardenia مثيرًا للاهتمام.

: +1: شكرا @ جاردينيا. بالمناسبة ، كشف بحثي الخاص حول الأداء في حالة الاستخدام الخاصة بي أنه في حالتي ، لم يتم تقسيم الردود ، ولكن أداء urllib3 أسرع بنسبة 20 +٪ من الطلبات ، لذلك هناك بعض النفقات العامة التي يتم تقديمها والتي أريد وصفها. لا يزال يتماشى مع عنوان هذه المشكلة ، ولكن السبب الجذري مختلف.

رائعة ، شكرا للمشاركة! :)

يبدو أنه هدف رائع يجب أن يتصدى له Hyper الخاص بـ

alex - لقد

في الطلبات ، حاولت بشكل مضارب استبدال استدعاء self.raw.stream بالتنفيذ المضمن لـ stream () (من urllib3). يبدو أنه يجعل الإنتاجية أقرب كثيرًا بين الطلبات و urllib3 ، على الأقل على جهازي:

--- requests.repo/requests/models.py    2015-03-06 16:05:52.072509869 +0000
+++ requests/models.py  2015-03-07 20:49:25.618007438 +0000
@@ -19,6 +19,7 @@
 from .packages.urllib3.fields import RequestField
 from .packages.urllib3.filepost import encode_multipart_formdata
 from .packages.urllib3.util import parse_url
+from .packages.urllib3.util.response import is_fp_closed
 from .packages.urllib3.exceptions import (
     DecodeError, ReadTimeoutError, ProtocolError, LocationParseError)
 from .exceptions import (
@@ -652,8 +654,12 @@
             try:
                 # Special case for urllib3.
                 try:
-                    for chunk in self.raw.stream(chunk_size, decode_content=True):
-                        yield chunk
+                    while not is_fp_closed(self.raw._fp):
+                        data = self.read(amt=chunk_size, decode_content=True)
+
+                        if data:
+                            yield data
+
                 except ProtocolError as e:
                     raise ChunkedEncodingError(e)
                 except DecodeError as e:

ربما يمكنك تجربة الشيء نفسه على جهازك لمعرفة ما إذا كان سيحدث فرقًا بالنسبة لك أيضًا.

(ملاحظة نعم ، أعلم أن الاتصال بـ is_fp_closed هو خرق للتغليف ، ولا يُقصد به أن يكون تصحيحًا خطيرًا مجرد نقطة بيانات)

shazow انها أملي أن BufferedSocket أن الاستخدامات فرط ينبغي أن تعالج الكثير من ذلك عدم الكفاءة، من خلال منع أساسا صغير يقرأ. أتساءل عما إذا كان httplib في Py3 يعاني من هذه المشكلة ، لأنه يستخدم io.BufferedReader نطاق واسع ، والذي يجب أن يوفر نفس نوع الفائدة تقريبًا مثل BufferedSocket .

بالتأكيد ، عندما ينمو hyper ما يكفي من وظائف HTTP / 1.1 لتكون مفيدة ، يجب أن نحاول قياسها جنبًا إلى جنب مع هذه التطبيقات الأخرى وبذل الجهود لكسب hyper بأسرع ما يمكن.

غير نشط لمدة عام تقريبًا. إغلاق.

أرى مشكلات مماثلة ، معدل نقل أقل بمقدار 10x باستخدام requests مقارنة بـ urllib3 .

أعتقد أن المشكلة تعيش داخل فئة urllib3 HTTPResponse ، عندما تتم قراءتها كمكرر ، يكون معدل نقلها سيئًا حقًا. حصلت على الكود الخاص بي يعمل مع اختراق قبيح للغاية: أعيد الكائن httplib.HTTPResponse الذي تحته خط والذي يستخدمه urllib3 ويبدو أن هذا يصلح مشكلة الإنتاجية الخاصة بي.

حقيقة مثيرة للاهتمام: الطبقة الفائقة من urllib3 HTTPResponse هي io.IOBase . الطبقة الفائقة لـ Python3 httplib.HTTPResponse هي io.BufferedIOBase . أتساءل ما إذا كان له علاقة بهذا.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات