2017年12月4Dのマルチスレッドを使って処理時間を短縮するテーブルに1万件を超えるHTMLファイルがあって、それらの中から所定のタグを抽出して別のテーブルに保存する、ような課題がありました。インタープリタモードでXeonプロセッサでも2時間以上かかっていました。同時にマルチタスクで実行すれば、使っているXeonが4コアなので1/4の処理時間、つまり30分で終わるようになるはずです。Serverのモニタ画面で見ていると、CPUは25%くらいしか使われていません。4Dプロセスはインタープリターモードでは1つのコアしか使わないのです。コンパイルしてプリエンプティブ(Preemptive)モードで実行すると、「プロセス管理はシステムへと委任され、マルチコアのマシンではシステムはプロセスをそれぞれのCPUへと個別に割り当てる」とされています。http://doc.4d.com/4Dv16/4D/16.3/Preemptive-4D-processes.300-3651705.ja.html#2821655果たしてCPUは100%使われるのでしょうか。プリエンプティブマルチスレッドで実行するためには3つの敷居があります。マルチプロセス、プリエンプティブ、コンパイルの3つです。マルチプロセスで動くように記述されたメソッドを、スレッドセーフ(プリエンプティブモード)で、コンパイルして実行する必要があります。3つの敷居を乗り越えるように元のソースを修正するには少々手間がかかります。コンパイルするだけで早くなるかもと、次の順に試していきました。コンパイル1.【デザイン】→【コンパイル開始】2.【実行】→【コンパイル済み再起動】これだけです。20%ほど速くなります。メニューを実行するだけですので簡単です。メソッドやフォームを編集しているときは【インタープリタで再起動】しなくてはなりません。Serverで複数の開発者が編集中の場合は恩恵をうけることができません。そこで問題の処理をコンポーネント化することにしました。遅い処理をコンポーネントに記述してコンポーネントだけをコンパイルしておき、ホストプロジェクトは編集可能なインタープリターで運用する、という作戦です。マルチプロセス(マルチスレッド)手始めにプリエンプティブではなく、コオペラティブ(Cooperative)プロセスで、マルチスレッドを実行してみました。processは以前からあって使ったことがあります。Workerはv15から使えるようになったコマンドです。Workerを試してみます。Workerの使用例プリエンプティブでなくてもマルチプロセス化するだけで20%ほど速くなります。データベースをクエリしたり保存したりするときに、ハードディスクのファイルI/OなどでCPUに待ち時間が発生していると考えられます。プリエンプティブマルチスレッドスレッドセーフという敷居があります。プリエンプティブマルチスレッドで実行するためには対象部分のメソッドがスレッドセーフでコンパイルされている必要があります。ここでは明示的にメソッドプロパティで「プリエンプティブプロセスで実行可能」をチェックします。呼び出しているメソッドすべてにこの設定をします。この設定をしておくと、メソッド内部でスレッドアンセーフなコマンドを呼び出しているとコンパイルエラーになって便利です。4Dコマンドにもスレッドアンセーフなコマンドがあります。【コンパイル開始】するとスレッドセーフなメソッドができます。Sierraで試しました。i7の2コアで、4スレッド使えるようです。アクティビティモニタでCPU使用率を確認すると、コオペラティブモードでは97%くらいでしたが、これが390%とか400%近い数値になります。これでプリエンプティブになっていることがわかります。速度は4倍より遅いと感じましたが、元のよりも十分に速いです。bitのため、プリエンプティブにしても恩恵が無いにもかかわらず、コンパイルとマルチプロセス化でかなり速くなりました。