ちょっとしたサイズのファイルを添付したメールを作成するコードを
Ruby で書いたのですが、いくつか速度上の問題にぶつかっています。
まず、以下のコードを。
#-------- begin
require 'tmail'
date_now = Time.now
filename = '/var/tmp/test.pdf'
mail = TMail::Mail.new
mail.from = TMail::HeaderField.new('From', 'test+from / idaemons.org')
mail.to = 'test+to / idaemons.org'
mail.date = date_now
mail.subject = 'test'
mail.mime_version = '1.0'
mail.set_content_type 'multipart', 'mixed', { 'boundary' => TMail.new_boundary }
textpart = TMail::Mail.new
textpart.set_content_type 'text', 'plain', { 'charset' => 'iso-2022-jp' }
textpart.body = "This is a test mail with an attachment.\n"
mail.parts << textpart
filepart = TMail::Mail.new
filepart.set_content_type 'application', 'pdf'
filepart.disposition = TMail::HeaderField.new('Content-Disposition',
'attachment; filename="' + File::basename(filename) + '"')
filepart.encoding = 'Base64'
#filepart.body = `uuenview -b #{filename}`
filecontent = File.open(filename).read
filepart.body = [filecontent].pack('m')
mail.parts << filepart
mail.write_back
print mail.encoded
#-------- end
テストに使った test.pdf は 700KB ほどのファイルです。
まず、 Ruby 1.6 を使って巨大な文字列を Array#pack で Base64
エンコードさせるととんでもない時間がかかってしまうのです。手元の
Pentium III 800MHz のマシンでは、エンコードになんと丸々 2 分も
かかりました。 (ファイルの読み込み〜格納は一瞬)
コメントアウトしてあるように外部のコマンド (uuenview) を使うと
瞬時 (0.1〜0.2 秒) に終わるのですが、三桁も違うとは。
なお、 Ruby 1.7 では rb_str_buf_cat() が導入され、最初に大きな
領域を確保しておいて再割り当てせずに使うようになっているため、
劇的に速度が改善しています。(0.2 秒ほどで終わりました)
そこで一つ要望なんですが、この変更を 1.6 にも持ってきませんか?
* * *
次に、性能上の問題になっているのが TMail::Mail#write_back です。
Base64 エンコードされたファイルのボリュームは 950KB 程なのですが、
write_back に 8 秒前後もかかるのです。
上の例の場合、 filepart の本文部分についてはキャラクタセットや
改行コードの変換は不要なので、「黙ってそのまま使ってくれ」という
指定ができればいいのですが、 TMail 側にそういう機能を用意できない
でしょうか?
例えば、本文の中身には関知しないメソッドとして write_back!,
encoded!, decoded! を新設するというのはいかがでしょう?
# あまり TMail の中身をよく見たわけじゃないので、使い方を間違って
# いるだけだったらすみません。
--
/
/__ __ Akinori.org / MUSHA.org
/ ) ) ) ) / FreeBSD.org / Ruby-lang.orgn
Akinori MUSHA aka / (_ / ( (__( @ iDaemons.org / and.or.jp
"Freeze this moment a little bit longer, make each impression
a little bit stronger.. Experience slips away -- Time stand still"