From: kosaki.motohiro@... Date: 2014-07-11T19:19:22+00:00 Subject: [ruby-dev:48402] [ruby-trunk - Feature #9981] [Assigned] Net::SMTP#send_message が大量の write(2) を発行する Issue #9981 has been updated by Motohiro KOSAKI. Tracker changed from misc to Feature Status changed from Open to Assigned Assignee set to Motohiro KOSAKI コードは問題なさそうに見えるし、賛成意見もついているし、メンテナがいないモジュールのようなので、 代理コミットしときますね。 ---------------------------------------- Feature #9981: Net::SMTP#send_message が大量の write(2) を発行する https://bugs.ruby-lang.org/issues/9981#change-47722 * Author: Masahiro Tomita * Status: Assigned * Priority: Normal * Assignee: Motohiro KOSAKI * Category: * Target version: ---------------------------------------- `Net::SMTP#send_message` でメールを送信すると1行毎に write(2) が発行されます。 1MB のバイナリデータを添付すると、18000回以上 write することになります。 1048576(byte) * 4/3 (Base64化) / 76 (1行あたりの長さ) = 18396 行 SMTP の DATA 命令後はひたすらデータを送り続ければいいだけなので行ごとに write するよりもバッファリングした方がいいと思います。 ```diff diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index 5fd4f8e..64e536a 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -901,10 +901,17 @@ module Net end res = critical { check_continue get_response('DATA') - if msgstr - @socket.write_message msgstr - else - @socket.write_message_by_block(&block) + socket_sync_bak = @socket.io.sync + begin + @socket.io.sync = false + if msgstr + @socket.write_message msgstr + else + @socket.write_message_by_block(&block) + end + ensure + @socket.io.flush + @socket.io.sync = socket_sync_bak end recv_response() } ``` これで write(2) が 350回程度になりました。 -- https://bugs.ruby-lang.org/