Forum: Ruby-dev [ruby-trunk - misc #9981] Net::SMTP#send_message が大量の write(2) を発行す

Eabad423977cfc6873b8f5df62b848a6?d=identicon&s=25 unknown (Guest)
on 2014-07-11 08:48
(Received via mailing list)
Issue #9981 has been updated by Hiroshi SHIBATA.


どなたか SMTP にお詳しい方はいらっしゃいませんか.

----------------------------------------
misc #9981: Net::SMTP#send_message が大量の write(2) を発行する
https://bugs.ruby-lang.org/issues/9981#change-47699

* Author: Masahiro Tomita
* Status: Open
* Priority: Normal
* Assignee:
* 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回程度になりました。
D37d474748a040cddbbc04774701d4ce?d=identicon&s=25 Takahiro Kambe (Guest)
on 2014-07-11 16:13
(Received via mailing list)
In message
<redmine.journal-47699.20140711064732.e1bfc429d603f917@ruby-lang.org>
  on Fri, 11 Jul 2014 06:47:32 +0000,
  shibata.hiroshi@gmail.com wrote:
> Issue #9981 has been updated by Hiroshi SHIBATA.
>
>
> $B$I$J$?$+(B SMTP $B$K$*>\$7$$J}$O$$$i$C$7$c$$$^$;$s$+(B.
$B>\$7$$$+$I$&$+$O$5$F$*$-!"(B

> SMTP $B$N(B DATA $BL?Na8e$O$R$?$9$i%G!<%?$rAw$jB3$1$l$P$$$$$@$1$J$N$G9T$4$H(B
> $B$K(B write $B$9$k$h$j$b%P%C%U%!%j%s%0$7$?J}$,$$$$$H;W$$$^$9!#(B
DATA$B$rAw$C$?$H$O!"$=$NDL$j$J$N$GLdBj$J$$$O$:$G$9!#(B
DATA$B$N=*$o$j$N(B".\r\n"$B$rAw$C$?8e$G$J$$$H!"%5!<%P!<$b1~Ez$rJV$;$^$;$s$+(B
$B$i!#(B
This topic is locked and can not be replied to.