0

コールセンターを運営している私の友人のために、以下のアルゴリズムを書いて、ファイル名をフォーマットし、月と日付に従ってディレクトリを移動したいだけです。しかし、コール センターには 350 万を超えるファイルがあり、プログラムは 12 時間動作し、20 GB 未満しか処理していないようです。

以下のアルゴリズムを最適化する方法はありますか?

class Program
{        
    // How much deep to scan. (of course you can also pass it to the method)
    const int HowDeepToScan = 20;

    static void Main(string[] args)
    {
        ProcessDir(@"E:\Hard Disk 2\", 1);
        Console.WriteLine("Islem Bitmistir");
        Console.ReadLine();
    }

    public static void ProcessDir(string sourceDir, int recursionLvl)
    {
        if (recursionLvl <= HowDeepToScan)
        {
            ChangeDirectories(sourceDir);

            // Recurse into subdirectories of this directory.
            string[] subdirEntries = Directory.GetDirectories(sourceDir);
            foreach (string subdir in subdirEntries)
                // Do not iterate through reparse points
                if ((File.GetAttributes(subdir) &
                     FileAttributes.ReparsePoint) !=
                         FileAttributes.ReparsePoint)
                    ProcessDir(subdir+@"\",recursionLvl + 1);
        }
    }

    public static void ChangeDirectories(string givenPath)
    {
        DataTable resultSet = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter();
        SqlCommand cmd = new SqlCommand();
        SqlConnection callCenterConnection = new SqlConnection(@"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CallCenter;Data Source=.");
        //Directory of mp3s
        string sourceDir = givenPath;
        //Get the files inside that directory
        string[] fileEntries = Directory.GetFiles(sourceDir);
        callCenterConnection.Open();
        //Iterate through those files
        foreach (string fullFileName in fileEntries)
        {
            //Get the file name without path and extension
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullFileName);
            adapter = new SqlDataAdapter("SELECT TOP 1 ID,Time,Tel,AgentID FROM ResultTable WHERE ID=" + fileNameWithoutExtension, callCenterConnection);
            adapter.Fill(resultSet);
        }
        adapter.Dispose();
        if (resultSet.Rows.Count != 0)
        {
            foreach (DataRow dr in resultSet.Rows)
            {
                DateTime fileDate = Convert.ToDateTime(dr["Time"]);
                if (!File.Exists(@"E:\Ses Dosyalari" + @"\" + fileDate.Year + @"\" + fileDate.Month + @"\" + Convert.ToString(dr["Time"]).Replace(":", ".") + " - " + Convert.ToString(dr["Tel"]) + " - " + Convert.ToString(dr["AgentID"]) + ".mp3"))
                {
                    File.Move(sourceDir + Convert.ToString(dr["ID"]) + ".mp3", @"E:\Ses Dosyalari" + @"\" + fileDate.Year + @"\" + fileDate.Month + @"\" + Convert.ToString(dr["Time"]).Replace(":", ".") + " - " + Convert.ToString(dr["Tel"]) + " - " + Convert.ToString(dr["AgentID"]) + ".mp3");
                    cmd = new SqlCommand("UPDATE ResultTable SET Used = 1 WHERE ID="+Convert.ToString(dr["ID"]), callCenterConnection);
                    cmd.ExecuteNonQuery();
                }
            }
        }
        cmd.Dispose();
        callCenterConnection.Close();
        resultSet.Clear();
        resultSet.Dispose();
    }
} 
4

1 に答える 1

0

ボトルネックがコードのパフォーマンス特性ではなく、場所間のネットワークである可能性はかなり高いです。

とはいえ、特に 2 番目の方法には最適化の余地が十分にあります。

まず、常にデータベースからのデータをまとめて操作します。一度に 1 つのレコードの存在を確認するのはコストがかかります。一度にすべてを読み取り、リストに入れます。上記のリストを繰り返し処理して、移動/ステータスの更新を実行します。

2 つ目は、文字列を連結するためにorを+使用します(または、お好みであれば a を使用します)。String.FormatString.ConcatStringBuilder

この操作で最も負担のかかるリソースはネットワークであるため、圧縮ライブラリを使用してディレクトリのすべてのファイルをラップし (少なくとも)、それをリモート サイトに送信し、プロセスで解凍して送信することをお勧めします。完了通知を返します。送信量が少ないほど効果的です。

于 2012-08-31T07:38:19.477 に答える