Path: sran265!katsu From: katsu@sran14.sra.co.jp (Katsuhiro Watanabe) Message-ID: Date: 17 Mar 92 10:32:29 Organization: Software Research Associates, Inc.,Japan Newsgroups: sra.os.unix,sra.sys.news Followup-To: sra.os.unix Subject: The small packet probrem and its solution Distribution: sra (Followup-To に注意)  sra で一番フォローが遅い渡邊ですが、なんと1年越しの話です。以前から 他人より仕事が遅いとは思ってたんですが、記事を書くのに半年かかって しまいました。  ちょうど1年前の今頃、sra.sys.news で、 「inet ドメインのストリーム型ソケットでのデータのやりとりの方法によって、 転送にかかる時間に10倍程度の開きが生ずる」 という話がありました。これは結局、「小さいパケットの抑制」という TCP の 実装技術からくるものだということがわかったので報告します。  まずこの記事では、既に expire されてしまったであろう議論の要約をし、 引き続く次の記事で、この問題の解析をします。 > From: nitta@sran10.sra.co.jp (Minoru Nitta) > Newsgroups: sra.sys.news > Subject: Question about inet domain stream socket (In Japanese/Kanji) > Message-ID: <259@sran10.sra.co.jp> > Date: 28 Mar 91 02:04:20 GMT > > こんにちは、新田@ソフト工研=>阪大です。 > > inetドメインのストリーム型のソケットについて: > > 今ソケットを使って二つのプログラムがデータをやりとりする > システムを作っているのですが、このシステムをNWS841(NEWS-OS 3.3) > の上で動かすと、1500バイトを越えるデータをやりとりすると、 > readが以上に速くになります。 > > OS 4.0ではこの現象は起きません。  ここでは、状況が「1500バイト」という魔術的な数で語られていますが、 これは Mtu の値(多分 1536 - 40 = 1496) からくるものでしょう。  なおこの現象は、後の新田さんの記事にもある通り、閾値は異なるものの OS 4.0 でも 4.1 でも SunOS でもほとんどどんな環境でも観測できます。 > From: nisimura@sra.co.jp (Tohru Nisimura) > Message-ID: <981@sranha.sra.co.jp> > > どのようなプログラムで、どのように計測しましたか?  私は最初この指摘の重大さに気がつきませんでしたが、次の記事で 示す通り、計測のしかた(write(2) の呼び方)が TCP プロトコルに 大きな影響を与えています。 > From: nitta@sran10.sra.co.jp (Minoru Nitta) > Message-ID: <260@sran10.sra.co.jp> > > 測定のためのプログラムを後につけます。 > 時刻をデータを書く前と相手から戻ってきた後に gettimeofday でとって > その差を表示しています。 > 実行して見ていると、1500バイトから速くなるのがわかるので > gettimeofday の誤差ではないと思います。  この記事に新田さんの測定プログラムが載っていますが、特にソケットとの read/write だけに着目すると、次のような構造になっています。 int datasize; char s[3000]; /* 送受信データの置き場所 */ /* 実際の新田さんのプログラムでは、ちゃんと全部読みきる/書ききるまで read(2)/write(2) を繰り返してる */ if (fork()) { for (;;) { read(socket, &datasize, sizeof(datasize)); read(socket, s, datasize); write(socket, &datasize, sizeof(datasize)); wrire(socket, s, datasize); } } else { struct timeval 始, 終; for (datasize = 100; datasize < sizeof(s); datasize += 100) { gettimeofday(&始, 0); write(socket, &datasize, sizeof(datasize)); wrire(socket, s, datasize); read(socket, &datasize, sizeof(datasize)); read(socket, s, datasize); gettimeofday(&終, 0); datasize および、終と始の時間差を表示; } }  つまり、きまった大きさを単純に read/write するのではなく、 大きさを 100 から 2900 まで変化させて調べるために、前もって データの大きさ自身(int なので、おそらく 4 バイト)を受け送りします。  これが TCP プロトコルの状態に大きな影響を及ぼしていました。 > From: utashiro@sran84.sra.co.jp (Kazumasa Utashiro) > Message-ID: <307@sran84.sra.co.jp> > > 僕のマシン (3.2 かな?) で実行すると 600バイトから速くなりま > すね。400msec -> 20msec くらい。 > > あまり確かなことは言えませんが、mbuf の cluster を使うかどう > かというのが影響しているような気がします。NEWS のページサイ > ズは 4K あるので、1500バイトの MTU なら1ページに入ってしまう > し、データリンク層から cluster へのデータ転送はページテーブ > ルの書換えだけで行なえるので cluster を使う方が速いのですが、 > 512バイト/ページの VAX の実装を参考にしてたりすると、cluster > を使わずにいくつもの mbuf チェーンを使ってパケットを受けとる > ことがあるかもしれません。どの大きさから cluster を使うかと > いうところで、速度の差が出てくるのではないでしょうか。最近の > OS では、無条件に cluster を使うようになっているはずです。 > > でも、ぜーんぜん嘘かもしれない。  これは少なくとも主たる原因ではないようです。 > From: nitta@sran10.sra.co.jp (Minoru Nitta) > Message-ID: <261@sran10.sra.co.jp> > > いろんなマシンでやってみました。 > > sparc(SunOS Release 4.0.3-JLE1.0.3) > sun3(SunOS Release 4.0.3) > 1024バイトを越えるとreadが2回にわかれる。 > 2048バイトを越えるとreadが速くなる。 > > DECstation(ULTRIX V4.1 (Rev. 38)) > 3000バイトまでやってみたが全て1回でreadする。 > 最初から速い。 > > NEWS(NEWS-OS Release 4.0C) > 1500バイトを越えるとreadが2回にわかれる。 > 3000バイトまで全て遅い。 > > ここで遅いとは400msec、速いとはその1/10程度です。  NEWS OS 4.0 等で 3000Byte までの例が出ていますが、実は閾値が この 3000 になっていて、もう少し長くすると速い状況になります。  そもそも、1500 や 3000 というのはやや粗い表現で、1byte 単位で 調べると 1496 とか 2992 とかいう数字が出てくるはずです。  以前の議論はここまででした。 -- ----____----____ 渡邊克宏@ソフトウェア工学研究所(四谷)