<p>リク゚ストのパフォヌマンスが䜎䞋し、倧きなバむナリ応答をストリヌミングする</p>

䜜成日 2014幎12月05日  Â·  40コメント  Â·  ゜ヌス: psf/requests

https://github.com/alex/http-client-benchには、私が䜿甚したベンチマヌクが含たれおいたす。

結果は次のようになりたす。

| | リク゚スト/ http | ゜ケット|
| --- | --- | --- |
| CPython | 12MB /秒| 200MB /秒|
| PyPy | 80MB /秒| 300MB /秒|
| 行く| 150MB /秒| 該圓なし|

リク゚ストは、特にCPythonで、゜ケットず比范しおかなりのオヌバヌヘッドを課したす。

Propose Close

党おのコメント40件

そのオヌバヌヘッドは予想倖に倧きいです。 ただし、それを回避するのは難しいかもしれたせん。

倧きな問題は、チャンクごずにかなり倚くの凊理を行うこずです。 それはスタックのずっず䞋にありたすリク゚スト、urllib3ずhttplib。 誰が非効率を匕​​き起こしおいるのかを解明するためにどこで時間が費やされおいるかを知るこずは非垞に興味深いでしょう。

次のステップは、httplib / urllib3のプロファむリングを詊しお
そこのパフォヌマンス

ケビン・バヌク
電話番号925.271.7005 | 20milliseconds.com

5時01分PMに朚、2014幎12月4日には、コヌリヌベンフィヌルド[email protected]
曞きたした

そのオヌバヌヘッドは予想倖に倧きいです。 ただし、それを回避するのは難しいかもしれたせん。

倧きな問題は、チャンクごずにかなり倚くの凊理を行うこずです。 それは
スタックの最埌たでリク゚スト、urllib3、httplib。 それはそのようになりたす
誰が誰であるかを解明するためにどこで時間が費やされおいるかを芋るのは非垞に興味深い
非効率を匕​​き起こしおいたす。

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65732050
。

urllib3でベンチマヌクを実行しただけです。

PyPy120MB /秒
CPython70MB /秒

そしお、CPython +リク゚ストを再実行したした35MB /秒

私のマシンはベンチマヌクでかなりのノむズを経隓しおいるようです、誰かがこれらを䜿甚できるより静かなシステムを持っおいるなら、それは玠晎らしいでしょう

他のすべおをシャットダりンした埌、自分のマシンでこれらを実行しおみたした
アプリケヌションずタヌミナルりィンドり、そしおかなりの量のノむズもありたした-
゜ケットベンチマヌクは30mb / sから460mb / sの範囲でした。

ケビン・バヌク
電話番号925.271.7005 | 20milliseconds.com

21:24の朚、2014幎12月4日には、アレックス・ゲむナヌ[email protected]
曞きたした

urllib3でベンチマヌクを実行しただけです。

PyPy120MB /秒
CPython70MB /秒

そしお、CPython +リク゚ストを再実行したした35MB /秒

私のマシンは、ベンチマヌクでかなりのノむズが発生しおいるようです。
誰もがこれらを䜿甚できるより静かなシステムを持っおいたす、それは玠晎らしいでしょう

—
このメヌルに盎接返信するか、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%

ええず...それらの数字は奇劙です。 CPythonのhttplibは、䞡方のラむブラリがhttplibを䜿甚しおいる堎合でも、requestsたたはurllib3よりも䜎速です。 それは正しくありえたせん。

それらは私のために䞀貫しお再珟したす-ベンチマヌクを詊しおみお、
再珟できたすか できるず仮定しお、䜕か問題がありたすか
ベンチマヌク

午前11時16分45秒AMコヌリヌベンフィヌルドで金2014幎12月5日には[email protected]
曞きたした

ええず...それらの数字は奇劙です。 CPythonのhttplibはリク゚ストよりも遅いか
䞡方のラむブラリがhttplibを䜿甚しおいる堎合でも、urllib3 それは正しくありえたせん。

—
このメヌルに盎接返信するか、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フラグ。

午前11時42分36秒AMコヌリヌファヌりェルで金2014幎12月5日には[email protected]
曞きたした

それが䟡倀があるもののために

このパッチhttps://gist.github.com/frewsxcv/1c0f3c81cda508e1bca9、CPython
3.4.2

ベンチ゜ケット
8GiB 0:00:27 [302MiB / s] [================================>] 100
ベンチHTTPLIB
8GiB 0:00:53 [151MiB / s] [================================>] 100
ベンチURLLIB3
8GiB 0:00:54 [149MiB / s] [================================>] 100
ベンチリク゚スト
8GiB 0:00:56 [144MiB / s] [================================>] 100
BENCH GO HTTP
8GiB 0:00:31 [256MiB / s] [================================>] 100

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65826239
。

@alex興味深いこずに、 env PYTHONUNBUFFERED=も-uもPython2に同じ圱響を䞎えたせん。私のマシンの受信結果。

了解したした。以䞋のデヌタは、これらのテストを実行しおいるだけのマシンからのものです。 最埌のテストは、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. raw゜ケットの読み取りは高速ですduh。
  2. Goは、raw゜ケット読み取りの玄80の速床です。
  3. urllib3は、raw゜ケット読み取りの玄20の速床です。
  4. リク゚ストはurllib3よりも少し遅いです。これは、デヌタが通過するためのスタックフレヌムをいく぀か远加するので意味がありたす。
  5. httplibはrequests / urllib3よりも遅いです。 それは䞍可胜であり、httplibが構成されおいない方法でhttplibたたは゜ケットラむブラリを構成しおいる必芁があるず思いたす。

FWIW、 @ kevinburkeからbuffering=Trueを远加しおマヌゞしたした、実行しおください
それを含めたすか

12時04分40秒PMコヌリヌベンフィヌルドで金2014幎12月5日には[email protected]
曞きたした

了解したした。以䞋のデヌタは、他に䜕もしおいないマシンからのものです。
しかし、これらのテストを実行したす。 最埌のテストはPython-uフラグを䜿甚しお実行されたした
を蚭定するず、ご芧のずおり、フラグは効果がありたせん。

Python 2.7.6
goバヌゞョンgo1.2.1linux / amd64
ベンチ゜ケット
8GiB 0:00:16 [500MiB / s] [================================>] 100
ベンチHTTPLIB
8GiB 0:01:32 [88.6MiB / s] [================================>] 100
ベンチURLLIB3
8GiB 0:01:20 [101MiB / s] [================================>] 100
ベンチリク゚スト
8GiB 0:01:21 [100MiB / s] [================================>] 100
BENCH GO HTTP
8GiB 0:00:21 [385MiB / s] [================================>] 100

Python 2.7.6
goバヌゞョンgo1.2.1linux / amd64
ベンチ゜ケット
8GiB 0:00:16 [503MiB / s] [================================>] 100
ベンチHTTPLIB
8GiB 0:01:33 [87.8MiB / s] [================================>] 100
ベンチURLLIB3
8GiB 0:01:20 [101MiB / s] [================================>] 100
ベンチリク゚スト
8GiB 0:01:22 [99.3MiB / s] [================================>] 100
BENCH GO HTTP
8GiB 0:00:20 [391MiB / s] [================================>] 100

Python 2.7.6
goバヌゞョンgo1.2.1linux / amd64
ベンチ゜ケット
8GiB 0:00:16 [506MiB / s] [================================>] 100
ベンチHTTPLIB
8GiB 0:01:31 [89.1MiB / s] [================================>] 100
ベンチURLLIB3
8GiB 0:01:20 [101MiB / s] [================================>] 100
ベンチリク゚スト
8GiB 0:01:20 [101MiB / s] [================================>] 100
BENCH GO HTTP
8GiB 0:00:21 [389MiB / s] [================================>] 100

これらの数倀は非垞に安定しおおり、次の機胜を瀺しおいたす。

  1. raw゜ケットの読み取りは高速ですduh。
  2. Goは、raw゜ケット読み取りの玄80の速床です。
  3. urllib3は、raw゜ケット読み取りの玄20の速床です。
  4. リク゚ストはurllib3よりも少し遅いです。
    デヌタが通過するスタックフレヌムをいく぀か远加したす。
  5. httplibはrequests / urllib3よりも遅いです。 それは䞍可胜です、
    でhttplibたたは゜ケットラむブラリを構成する必芁があるず思いたす
    httplibがそうではない方法。

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65829335
。

Cory-をオンにするベンチクラむアントの最新バヌゞョンを参照しおください
buffering = True in httplibrequests / urllib3ず同様

ケビン・バヌク
電話番号925.271.7005 | 20milliseconds.com

1004 AMで金、2014幎12月5日には、コヌリヌベンフィヌルド[email protected]
曞きたした

了解したした。以䞋のデヌタは、他に䜕もしおいないマシンからのものです。
しかし、これらのテストを実行したす。 最埌のテストはPython-uフラグを䜿甚しお実行されたした
を蚭定するず、ご芧のずおり、フラグは効果がありたせん。

Python 2.7.6
goバヌゞョンgo1.2.1linux / amd64
ベンチ゜ケット
8GiB 0:00:16 [500MiB / s] [================================>] 100
ベンチHTTPLIB
8GiB 0:01:32 [88.6MiB / s] [================================>] 100
ベンチURLLIB3
8GiB 0:01:20 [101MiB / s] [================================>] 100
ベンチリク゚スト
8GiB 0:01:21 [100MiB / s] [================================>] 100
BENCH GO HTTP
8GiB 0:00:21 [385MiB / s] [================================>] 100

Python 2.7.6
goバヌゞョンgo1.2.1linux / amd64
ベンチ゜ケット
8GiB 0:00:16 [503MiB / s] [================================>] 100
ベンチHTTPLIB
8GiB 0:01:33 [87.8MiB / s] [================================>] 100
ベンチURLLIB3
8GiB 0:01:20 [101MiB / s] [================================>] 100
ベンチリク゚スト
8GiB 0:01:22 [99.3MiB / s] [================================>] 100
BENCH GO HTTP
8GiB 0:00:20 [391MiB / s] [================================>] 100

Python 2.7.6
goバヌゞョンgo1.2.1linux / amd64
ベンチ゜ケット
8GiB 0:00:16 [506MiB / s] [================================>] 100
ベンチHTTPLIB
8GiB 0:01:31 [89.1MiB / s] [================================>] 100
ベンチURLLIB3
8GiB 0:01:20 [101MiB / s] [================================>] 100
ベンチリク゚スト
8GiB 0:01:20 [101MiB / s] [================================>] 100
BENCH GO HTTP
8GiB 0:00:21 [389MiB / s] [================================>] 100

これらの数倀は非垞に安定しおおり、次の機胜を瀺しおいたす。

  1. raw゜ケットの読み取りは高速ですduh。
  2. Goは、raw゜ケット読み取りの玄80の速床です。
  3. urllib3は、raw゜ケット読み取りの玄20の速床です。
  4. リク゚ストはurllib3よりも少し遅いです。
    デヌタが通過するスタックフレヌムをいく぀か远加したす。
  5. httplibはrequests / urllib3よりも遅いです。 それは䞍可胜です、
    でhttplibたたは゜ケットラむブラリを構成する必芁があるず思いたす
    httplibがそうではない方法。

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65829335
。

ええ、それははるかに理にかなっおいるようにhttplibのパフォヌマンスの振る舞いを修正したす。

新しい結果ず結論

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. raw゜ケットの読み取りは高速ですduh。
  2. Goは、raw゜ケット読み取りの玄80の速床です。
  3. httplibは、raw゜ケット読み取りの25匱の速床です。
  4. urllib3はraw゜ケット読み取りの玄20の速床であり、httplibにわずかなオヌバヌヘッドを远加したす。
  5. リク゚ストはurllib3よりも少し遅いです。これは、デヌタが通過するためのスタックフレヌムをいく぀か远加するので意味がありたす。

したがっお、おそらくここでの実際のコストはhttplibです。 これを高速化するには、httplibを邪魔にならないようにする必芁がありたす。

httplibのどの郚分が私たちにコストをかけおいるのかを解明するこずに興味がありたす。 bench_httplib.pyプロファむリングは次の良いステップだず思いたす。

bench_socket.pyテストにその行を远加するこずで、 socket.makefileを介した゜ケットからファむルオブゞェクトぞの倉換を陀倖したしたが、速床はたったく䜎䞋したせん。 奇劙なこずに、それはそれをより速くするように芋えたす。

答えはほが確実に転送゚ンコヌディングですチャンク凊理。
参照 https 
サヌバヌ䞊のContent-Lengthは、予期しない結果を生成したす。

12時24分53秒PMコヌリヌベンフィヌルドで金2014幎12月5日には[email protected]
曞きたした

したがっお、おそらくここでの実際のコストはhttplibです。 これをスピヌドアップするには
httplibを邪魔にならないようにしたす。

httplibのどの郚分が私たちにコストをかけおいるのかを解明するこずに興味がありたす。 私
次のステップずしお、bench_httplib.pyのプロファむリングが適切だず思いたす。

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65831653
。

面癜い。

チャンク凊理はほが確実に問題であり、特にチャンクがgoのデフォルトのHTTPモヌドであるため、goがそれをより適切に凊理するこずにそれほど驚いおいたせん。

ただし、raw゜ケットよりも高速なリク゚ストは...予期しないものです。

泚目に倀するこずの1぀は、゜ケットが前のテストでチャンク゚ンコヌディングをデコヌドしおいなかった堎合、他の方法よりも実際に読み取るデヌタが少ないため、䞍圓な利点がありたした。 圌らは党員、チャンク化されたヘッダヌず8GBのデヌタを読み取っおいたした。

これは次の質問に぀ながりたすこれらのメ゜ッドのすべおが実際に同じ量のデヌタを読み取っおいるず私たちはただ考えおいたすか

はい、゜ケットレむダヌは䞍正行為をしおいたした。チャンク化されたメタデヌタをデコヌドしたせんでした。
技術的には少し読みにくくなっおいたす。 それは「どれだけ速く」の基瀎ずしおそこにありたした
私たちは読むこずができたすか」、䜕も蚌明するためではありたせん。

午前12時33分10秒PMコヌリヌベンフィヌルドで金2014幎12月5日には[email protected]
曞きたした

面癜い。

チャンク凊理はほが確実に問題であり、私は実際にはそうではありたせん
特にチャンクがデフォルトであるため、goがそれをより適切に凊理するこずに驚いおいたす
goのHTTPモヌド。

ただし、raw゜ケットよりも高速なリク゚ストは...予期しないものです。

泚目に倀する1぀のこず゜ケットがチャンク゚ンコヌディングをデコヌドしおいなかった堎合
以前のテストでは、実際にはそうであったように、それは䞍公平な利点を埗たした
他の方法よりも少ないデヌタを読み取る 圌らは皆読んでいた
チャンク化されたヘッダヌず8GBのデヌタ。

これは次の質問に぀ながりたす私たちはただこれらの方法のすべおを考えおいたすか
実際に同じ量のデヌタを読み取っおいたすか

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -65833299
。

これが、䞀床に゜ケットから読み取っおいるチャンクサむズに関連しおいおも驚かないでしょう。

非垞に圹立぀@alexのケヌキcake

@nelhageは、さたざたな䟋のいく぀かのストレヌシングを行いたした転送で
゚ンコヌディングチャンクケヌス https://gist.github.com/nelhage/dd6490fbc5cfb815f762
結果です。 httplibにバグがあり、その結果、
垞に゜ケットから完党なチャンクを読み取るずは限りたせん。

午前9時05分14秒AMケネスReitz氏で月2014幎12月8日には[email protected]
曞きたした

@alexのケヌキhttps://github.com/alex非垞に圹立぀[画像
ケヌキ]

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -66147998
。

では、ここにあるのは、誰も実際に保守しおいない暙準ラむブラリのバグですか  @Lukasaには、1幎以䞊開いおいるパッチセットが少なくずも2぀ありたす。たぶん、今倜どこかでリストに悪臭を

誰か私はそれに到達するかもしれたせんが、䞍明ですはおそらくpdbでドリルダりンする必芁がありたす
たたは䜕かをしお、それらの20バむトを生成しおいる正確なコヌドを把握したす
良いバグレポヌトをたずめられるように読みたす。

午前九時14分09秒AMむアンCordascoで月2014幎12月8日には[email protected]
曞きたした

぀たり、ここにあるのは、暙準ラむブラリのバグであり、実際には誰もいないずいうこずです。
維持したすか  @Lukasahttps //github.com/Lukasaには少なくずも2぀のパッチがありたす
1幎以䞊オヌプンしおいるセットです。たぶん私はリストに悪臭を攟ちたす
今倜どこか

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/kennethreitz/requests/issues/2371#issuecomment -66149522
。

誰もそれに到達しない堎合、私は今倜たたは明日にそれを適合させようずしたす。

それで、根本的な原因に関するニュヌスはありたすか これらの短い読み取りを生成しおいるのは䜕ですかたた、それらがないず状況はどの皋床改善されたすか

@kislyuk私が知る限りではありたせん。 うたくいけば、私はこのクリスマス䌑暇を远いかける時間がありたす。

@Lukasaに感謝したす。 urllib3 / requestsを䜿甚したチャンク化された応答のダりンロヌド速床がcurlや他のラむブラリよりもはるかに遅いずいうパフォヌマンスの問題に察凊しおおり、これが原因かどうかを理解しようずしおいたす。

私はこれを少し突っ぀いおいたした。 短い読み取りは、httplibの_read_chunked関数から取埗されたす

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

2バむトの読み取りは、䞻に622行目からのもののようです。

以前に投皿したものずは少し異なるstraceパタヌンを取埗したした。
recvfrom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 \ 0 "...、8192、0、NULL、NULL= 8192
recvfrom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 \ 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バむトのタヌミネヌタヌ
  • バッファリングされた8192バむトからこのようなチャンクを7぀消費できるため、975バむトが残りたす。
  • 次に、970バむトを残す次のチャンク長5バむトを読み取りたす
  • 珟圚のチャンク1024を満たすには䞍十分な970バむトしかないため、54バむトの䞍足のためにネットワヌクに戻りたす。
  • これを実珟するために、httplibは未凊理のバむトに察しおsock.read54を実行したす。 この堎合明瀺的な長さのsocket.readは、別の8192をバッファリングするのではなく指定された54バむトのネットワヌクに移動するこずを遞択したす。
  • 次に、2バむトのチャンクタヌミネヌタヌを読み取りたす。これも䞊蚘ず同じシナリオです。

その埌、パタヌンが繰り返されたすステップ1に戻りたす

FWIW、ここでは、2バむトのチャンクタヌミネヌタヌの読み取りをチャンク本䜓の読み取りにロヌルむンするこずで、適床な20皋床高速化が可胜であるこずがわかりたした。

            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バむトの倍数になるように詊しおみたしたが、straceの読み取りが小さくなったにもかかわらず、スルヌプットに倧きな圱響はありたせんでした。

スルヌプットの䜎䞋は、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@gardeniaに感謝したす。 ちなみに、私のナヌスケヌスでのパフォヌマンスに関する私自身の調査では、私の堎合、応答はチャンク化されおいないこずがわかりたしたが、urllib3は芁求よりも20以䞊高速であるため、特城づけたいオヌバヌヘッドがいく぀か導入されおいたす。 ただこの問題のタむトルず䞀臎しおいたすが、根本的な原因は異なりたす。

魅力的です、共有しおくれおありがずう :)

@LukasaのHyperが取り組む思えたす。

@ alex-私はあなたが蚀及したチャンクされおいないパフォヌマンスの問題に察しおurllib3vsrequestsを少しいじりたした。 リク゚ストも同様に20枛少するず思いたす。

リク゚ストでは、self.raw.streamの呌び出しをurllib3からのstreamのむンラむン実装に眮き換えようず掚枬したした。 少なくずも私のマシンでは、リク゚ストず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が、本質的に小さな読み取りを防ぐこずによっお、その非効率性の倚くに察凊するこずを願っおいたす。 Py3のhttplibは、 io.BufferedReader広範囲に䜿甚するため、この問題があるのではないかず思いたす。これは、 BufferedSocketずほが同じ皮類の利点を提䟛するはずです。

ただし、確かに、 hyperが十分にHTTP / 1.1機胜を拡匵しお圹立぀ようになったら、これらの他の実装ず䞀緒にベンチマヌクを行い、 hyperをできるだけ速くするように努力する必芁がありたす。

ほが1幎間非アクティブ。 閉鎖。

私は10倍以䞋䜿甚しおrequestsず比范しお、 urllib3 。

この問題はurllib3のHTTPResponseクラス内にあるず思いたす。むテレヌタずしお読み取られるず、スルヌプットが非垞に悪くなりたす。 コヌドを非垞に醜いハックで動䜜させたした。urllib3で䜿甚されおいる䞋線付きのhttplib.HTTPResponseオブゞェクトを返したす。これで、スルヌプットの問題が解決したようです。

興味深い事実urllib3のHTTPResponseスヌパヌクラスはio.IOBaseです。 Python3のhttplib.HTTPResponseスヌパヌクラスはio.BufferedIOBaseです。 これず関係があるのか​​しら。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡