大量のメールをサーバ上に残している状態No.03593
ながまる さん 18/07/03 01:12
 
こんにちは!


POP3 メールで「受信したメールをサーバー上に残す」をしている状態で、
メールサーバに非常に多くのメール (数十万通程度) が残されている状態でメールを
受信すると、
メールの一覧の取得 (UIDL) が終了後、メール本文のダウンロードが始まる何秒かの
間、
秀丸の UI がフリーズして操作できなくなります。

おそらく、 UIDL で受信したものと UIDL.bin の Unique ID を比較して、
受信するメールを解決している部分だと考えているのですが、
この部分に関して、

* UI をブロックしない (フリーズのようにならない)
* できれば、もうちょっと高速にする

といった改善を希望します。


Office 365 Outlook のようなクラウドメールと、
起動やメール検索が高速で、振り分け機能が強力な秀丸メールを併用するため、
「受信したメールをサーバに残す」設定で POP3 でメールを受信をして使用していま
す。
メールが多いと、あっという間にサーバ上のメールが数十万オーダーになってしまう
のですが、
この状態でメール受信を行うと、定期受信のたびに秀丸メール本体 の UI がフリー
ズしてしまっていて困っています。

(最近、秀丸メールの IMAP4 機能がだいぶ強化されてきていますが、
 過去だいぶ長いこと POP3 で受信し続けているので、
 これからも POP3 で受信し続けると思います…)


また、 フリーズしている間にどのような処理が行われているのかは想像でしかあり
ませんが、
もし仮に、 UIDL で受信したものと UIDL.bin の Unique ID の差集合を取得する処
理をしているだけであれば、
手元で似たようなロジックを試した限り、
実装を工夫すれば、秀丸メールがフリーズしている時間の 数分の1 〜 数十分の1
ぐらいの速度で行えると感じます。

ただし、 この部分を高速化しても、 メール一覧のダウンロード部分は早くならない
ので、
この高速化はそこまで強い希望ではありません。

[ ]
RE:03593 大量のメールをサーバ上に残してNo.03597
秀まるお2 さん 18/07/03 09:36
 
 サーバー上のメール通数が多い場合の、ダウンロード対象メールがどれか調べる処
理は、実はかなり苦労して高速化してるつもりではあります。一応、僕的にはこれ以
上高速にするのは無理かなぁというレベルまでがんばってるつもりです。

 UIが固まらないようにすることは、例えばUIDLの比較を別スレッドに追い出すこと
で実現可能だと思います。一回トライしてみたいと思いますが・・・

 ちなみに、現状で固まってる時間、何秒(あるいは何分?)くらいでしょうか。そ
んなには長く固まることは無いはずなんですけども。

[ ]
RE:03597 大量のメールをサーバ上に残してNo.03600
ながまる さん 18/07/03 13:02
 
別スレッドに追い出すのは是非お願いします!

固まっている時間は、 Core i7-4790 CPU 上で 20万通受信する場合ででせいぜい 3
〜5秒 程度なので、そこまで長くありません。
ただ、数分〜十数分毎にしている自動受信によって発生するので、鬱陶しいというの
が理由です。この鬱陶しさは、別スレッドに追い出せば解決すると思います。

もし、ダウンロード対象メールを求める処理が差集合を求めるだけなら、シャッフル
された20万件でも数百ms程度でできるのかな…と考えたのですが、
メール受信処理に明るくないので、見当違いだったら申し訳ありません…
検証コード: https://ideone.com/ksLHPF

[ ]
RE:03600 大量のメールをサーバ上に残してNo.03601
ながまる さん 18/07/03 13:59
 
すみません、ウソつきました。シャッフルされたものだと普通に1〜2秒くらいかかっ
てました…

処理時間の大半がソート部分なのと、たまたまメールサーバがソートした状態で UID
L を返してきていたので、数分の1 〜 数十分の1 で動くと実験結果が出てしまっ
ていました。

[ ]
RE:03600 大量のメールをサーバ上に残してNo.03602
秀まるお2 さん 18/07/03 14:10
 
 ソースコード見直してみたんですが、UIDLの比較よりも、リモートメール一覧の更
新の方が遅いような気がします。

 「全般的な設定 - 送受信 - リモートメール」の「通常の受信時に一覧を更新しな
い+終了時に一覧を消去」をONにすると高速になると思います。これをONしてどうか
試してみて欲しいです。

 それでもやはり何秒か固まるようでしたら、別スレッド化をトライしてみよかうな
ぁと思いますけども。

 あと、UIDLの比較の処理については、秀丸メールのデータ用フォルダの配下にある
アカウント用フォルダ配下にUIDL.binってファイルの中に、実際のUIDL文字列が入っ
てるんですが、たぶんその文字列でテストするともっと時間がかかるんじゃないかと
思います。

 秀丸メール内部では、文字列の比較はなるべく減らして、いわゆるハッシュ値を使
って比較をするような処理をしています。


[ ]
RE:03602 大量のメールをサーバ上に残してNo.03604
ながまる さん 18/07/04 02:07
 
> 「全般的な設定 - 送受信 - リモートメール」の「通常の受信時に一覧を更新し
>ない+終了時に一覧を消去」をONにすると高速になると思います。これをONしてど
>うか試してみて欲しいです。
>
> それでもやはり何秒か固まるようでしたら、別スレッド化をトライしてみよかう
>なぁと思いますけども。
>
設定してみましたが、残念ながら殆ど速度に違いはありませんでした。

「固まる時間」を 「Window に SendMessage して返ってこない時間」と定義し、
3回 受信を繰り返した平均フリーズ時間は、設定前は 4325ms、 設定後は 4313ms で
した。

別スレッド化を検討いただけると、うれしいです。


> あと、UIDLの比較の処理については、秀丸メールのデータ用フォルダの配下にあ
>るアカウント用フォルダ配下にUIDL.binってファイルの中に、実際のUIDL文字列が
>入ってるんですが、たぶんその文字列でテストするともっと時間がかかるんじゃな
>いかと思います。
>
> 秀丸メール内部では、文字列の比較はなるべく減らして、いわゆるハッシュ値を
>使って比較をするような処理をしています。
>
UIDL.bin の中身は受信順によってある程度きれいに並んでいるせいか、ランダムな
数値と比べると 2〜3割 早かったです。



> 処理時間の大半がソート部分なのと、たまたまメールサーバがソートした状態で U
>IDL を返してきていたので
>
この検証を実行した時は、秀丸は x86, 検証コードは x64 で動かしていたため、か
なり不公平な結果でした。
このため、

* 両方 x86 に揃える
* 「固まる時間」を 「Window に SendMessage して返ってこない時間」と定義
* 検証コードは https://ideone.com/ksLHPF の list1, list2 変数を シャッフルし
ていない UIDL.bin と メールサーバ の UIDL コマンドで取得したもの

として調査したところ、

検証コード: 1725ms
固まる時間: 4323ms

約2.5分の1 程度ので、「数分の1 〜 数十分の1」というのは事実ではありません
でした。申し訳ありません…
ここを早くしても、そんなにメリットは大きくなさそうです。

文字列をハッシュにして差集合を取得して、差集合の文字列を導出するうまいロジッ
クがすぐに思いつかなかったので、文字列そのまま使って比較してこの速度になりま
した。
ハッシュ値を使って比較すれば、確かにもっと早いかもしれません。。。

[ ]
RE:03604 大量のメールをサーバ上に残してNo.03607
秀まるお2 さん 18/07/04 08:44
 
 リモートメール一覧を更新しない設定でも速くならないということで・・・。失礼
しました。

 別スレッド化ってことで一回トライしてみます。

 ちなみに僕のマシンだと、ウイルス入りと思わしきメールを受信した時に秀丸メー
ルが数秒固まることが多いです。最近のWindows10になってからだと思いますけども。

[ ]
RE:03607 大量のメールをサーバ上に残してNo.03610
ながまる さん 18/07/04 10:09
 
お願いします。

試している OS は Windows 7 であることと、
送受信のコマンドをみる限り、固まるのは UIDL コマンド 受信完了後、 RETR コマ
ンド実行前なので、受信したメールの中身は関係ないのではないかと思っています。

[ ]
RE:03610 大量のメールをサーバ上に残してNo.03626
ながまる さん 18/07/05 23:28
 
以下のような std::hash を使った差集合のコードを、 VC++ で 最適化オプション /
Ox でビルドし、
実際の秀丸で 4000ms 固まる時に利用された UIDL.bin と UIDL コマンドで取得した
 ユニークID を利用して、差集合を求めてみたところ、
約 1/100 の 52ms で実行できました。

https://ideone.com/uBGbzu

まだかなり高速化の余地がありそうです。
参考まで。

[ ]
RE:03626 大量のメールをサーバ上に残してNo.03627
秀まるお2 さん 18/07/06 08:51
 
 ちなみに昨日アップロードしたVersion 6.84β8にて別スレッド化してますので、
とりあえずそれで大丈夫なはずではあります。

 UIDLの比較ですが、単純に2のリストに変換してら比較してって処理になってなく
て、1つ1つのUID文字列について、「このメールは新着メールか、ダウンロード済
みか、ダウンロードしない対象メールか、サーバーから削除しないメールか、新着だ
けどサイズ制限でダウンロードしないメールか」等と、さらにはリモートメール一覧
上での状態など、多次元の判定を繰り返すような処理になってます。それを今から2
つのリストにして比較するって風にはちょっと直せないと思います。

 ダウンロードした新しいUIDLの1行ずつを処理する中で、旧UIDLと比較する処理が
あって、以前は指数関数的に遅くなってたんですけども、Version 6.76の時に、その
比較の処理を、新旧のUIDLでの並び順が似ているというか、1日単位で見た場合はほ
ぼ同じであることを利用して高速化するようにして、それで指数関数的には遅くなら
ないようにはなりました。

[ ]
RE:03627 大量のメールをサーバ上に残してNo.03633
ながまる さん 18/07/06 20:22
 
なるほど、単純に差集合をとっているわけではないのですね。。。
指数的に増えるのでなければ、これ以上メールの数が増えても実用的な速度で済むと
思いますので、このままでも問題ないと思います。


> ちなみに昨日アップロードしたVersion 6.84β8にて別スレッド化してますので、
>とりあえずそれで大丈夫なはずではあります。
>
早速のご対応ありがとうございます!
試させていただきました。

残念ながら、 "メール一覧を取得中 (100%)" となってから、 "UIDL解析中..." に切
り替わる前までの間の 2秒 ほど、 UI が固まってしまいます。。。
以前より半分ほどの時間にはなったのですが、まだなにか UI をブロックする重い処
理が存在しているみたいです。
こちらも別スレッドに逃がすようにしていただけないでしょうか?

[ ]
RE:03633 大量のメールをサーバ上に残してNo.03634
秀まるお2 さん 18/07/06 20:56
 
 テストありがとうごさいます。

 まだ2秒固まるということで改めて調べてみたら、たしかに一部の重い処理がまだ
メインのスレッド側にありました。

 また修正して、来週中にまたβ版としてアップロードさせていただきます。

[ ]