別スレッドで処理を行うメリットはマルチCPUの恩恵みにある

比較に使用する処理
System.IO名前空間の「Directory.GetFiles」とSystem.Text.RegularExpressions名前空間の「Regex.IsMatch」を使用して特定のフォルダ以下にある全てのイメージファイルを取得する。
※当環境でファイル数が約50000弱,その内の約45000のファイルパスを取得する処理となる。

Sample Code

string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
string[] files = Directory.GetFiles(
    folderPath, "*", SearchOption.AllDirectories);

List<string> imgList = new List<string>();

for (int i = 0; i < files.Length; i++)
{
    //正規表現でイメージファイルかを判断し格納。
    if (regex.IsMatch(files[i])) imgList.Add(files[i]);
}


比較分類

  1. メインスレッド(シングルスレッド。通常の処理)で行う場合
  2. BackgroundWorkerを使用して別スレッドで行う場合

上記の処理を共に10回行い、処理に掛かる時間を比較する。

環境
  • OS:Windows Vista
  • CPU: Core2 Duo 2.66GHz
  • RAM: 2GB


1回の処理が終了するまで次の処理を行わない条件で計測する

1回の処理に掛かる時間の平均
  • メインスレッド:1225.477ms
  • 別スレッド:1236.175ms

結論
その差は約0.01秒。
相対的に比較して、この程度の処理で出される差は誤差と言える程度のものでしかなかった。


1回の処理が終了したかに関わらず、処理を行った場合

Sample Code(BackgroundWorkerを使用した処理のみ)
class Program
{
    static void Main(string[] args)
    {
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);

        for (int i = 0; i < 10; i++)
        {
            if (!bw.IsBusy)
            {
                bw.RunWorkerAsync();
            }
            else
            {
                NewThread();
            }
        }
    }

    static void NewThread()
    {
        BackgroundWorker nbw = new BackgroundWorker();
        nbw.DoWork += new DoWorkEventHandler(bw_DoWork);
        nbw.RunWorkerAsync();
    }

    static void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        string[] files = Directory.GetFiles(
            Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
            "*",
            SearchOption.AllDirectories
            );

        List<string> imgList = new List<string>();
        Regex regex = new Regex(@"\.(BMP|DIB|RLE|JPG|JPEG|JPE|JFIF|GIF|EMF|WMF|TIF|TIFF|PNG|ICO)$");

        for (int i = 0; i < files.Length; i++)
        {
            if (regex.IsMatch(files[i])) imgList.Add(files[i]);
        }

        e.Result = imgList.ToArray();
    }
}

10回処理を行ったトータルの処理時間

  • メインスレッド:11977.108ms
  • 別スレッド:6786.517ms


メインスレッドでループを回した処理に掛かった時間は1回の処理時間×ループ回数とほぼ一致するが、別スレッドで行われた処理では明らかに処理に掛かった時間が短縮された。

タスクマネージャでCPU使用率を見るとデュアルコアCPU環境では、シングルスレッドで処理を行わせた場合、片方のCPUしか使用されていないが、別スレッドで次々に処理を行わせた場合ではCPUをフルに使用して処理を行っていることを確認できる。
このため、別スレッドで次々に処理を行う方が処理に掛かる時間が短くなったと言える。

0 Comments:

Sony Style(ソニースタイル)
デル株式会社

Recent Posts