同事在處理大量資料的轉檔,專案用C#讀取大量文字檔案,讀取後要做基本欄位檢核,因為程式處理速度較慢(10萬筆20分鐘),於是幫忙同事一起抓原因。花了幾個小時後,發現重複New CultureInfo 對效能帶來巨大的影響,快來筆記。
日期欄位的檢核:
通常我們會用Datetime.TryParse或DateTime.TryParseExact這兩種方法檢核並輸出日期值。
*兩者差別在輸入的日期字串是否為標準的格式(ISO8601),當字串可能是非標準的格式時,程式可以會使用Datetime.TryParseExact指定格式。
DateTime.TryParseExact(
"20150709",
"yyyyMMdd",
new CultureInfo("zh-TW", true),
DateTimeStyles.None,
out dteDTE)
*yyyyMMdd是ISO8601標準的格式,其實用TryParse也可以。
參數說明:
其中第3個參數要輸入System.Globalization下的文化特性類別CultureInfo
這邊的寫法如果執行1次影響並不大,但因為這個段落要重複執行100萬次以上,時間就很漫長,來執行10萬次比較:
1.執行10萬次new CultureInfo (Datetime.TryParseExact)
[TestMethod]
public void TestMethod1()
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
DateTime dteDTE = new DateTime();
if (DateTime.TryParseExact("20150709", "yyyyMMdd", new CultureInfo("zh-TW", true), DateTimeStyles.None, out dteDTE))
{
continue;
}
}
sw.Stop();
Console.WriteLine(String.Format("總計時間:{0}毫秒", (sw.ElapsedMilliseconds).ToString()));
}
2.只執行1次new CultureInfo (Datetime.TryParseExact)
[TestMethod]
public void TestMethod2()
{
CultureInfo culTW = new CultureInfo("zh-TW", true);
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
DateTime dteDTE = new DateTime();
if (DateTime.TryParseExact("20150709", "yyyyMMdd", culTW, DateTimeStyles.None, out dteDTE))
{
continue;
}
}
sw.Stop();
Console.WriteLine(String.Format("總計時間:{0}毫秒", (sw.ElapsedMilliseconds).ToString()));
}
3.單純用Datatime.TryPasre
[TestMethod]
public void TestMethod3()
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
DateTime dteDTE = new DateTime();
if (DateTime.TryParse("20150709",out dteDTE))
{
continue;
}
}
sw.Stop();
Console.WriteLine(String.Format("總計時間:{0}毫秒", (sw.ElapsedMilliseconds).ToString()));
}
#Set | ms |
TryParseExact (new 10萬次 CultureInfo ) | 32995 |
TryParseExact (new 1次 CultureInfo ) | 29 |
TryParse | 20 |
小結:
- 32995ms vs 29ms,揉眼睛,真的沒看錯!是1,000倍,這個比半澤直樹最終回百倍返しだ!(百倍奉還)還強!
- 預計要轉200萬筆資料,33s * 20單位交易量 * 20個日期欄位 / 8t = 1650秒 ≃ 30分鐘節省。
- 選Datetime.TryParse或Datetime.TryParseExact都很快,只要不要選Datetime.Parse! 在轉換失敗時,效能會差很多。
- 20150709是女兒生日。
參考: