Wednesday, August 1, 2012

[C#] Using FileStream StreamWriter avoid IOException

今天在用JMeter對公司的程式作壓力測試,但是我發現錯誤率一直在0.5~1%,這是相當高的錯誤率,所以就來查啦。

從JMeter紀錄來看,錯誤訊息是這樣
System.IO.IOException: 由於另一個處理序正在使用檔案 'filename',所以無法存取該檔案。
System.IO.IOException: The process cannot access the file 'filename' because it is being used by another process.
原因是在程式中會去對實體檔案寫log,平時看不出錯誤,但是壓力測試下就會因為檔案lock住產生 IOException 。

原本的code長的這樣
public static void WriteLog()
      {
            StreamWriter log;

            if (!File.Exists("FilePath"))
            {
                log = new StreamWriter("FilePath");
            }
            else
            {
                log = File.AppendText("FilePath");
            }

            log.WriteLine("Write Something");
            log.Close();
      }

我先改成用Using StreamWriter,原因可以看這邊using Statement,但是再次測試時,發現錯誤率雖然降低了,可是還是有錯,這是不容許的啊!! 最後一時找不到方法,只好加上lock,然後就再也測不到 IOException 的錯誤,可以算是解決問題了,但是我想搞不好有更好的方法就是。

最後code改成這樣
private static readonly object LockFile = new object();
        public static void writeFile()
        {
            lock(LockFile)
            {
                using (var log = new StreamWriter("FilePath", true))
                {
                    log.WriteLine("Write Something");
                }
            }
        }
題外話,StreamWrite有個StreamWriter Constructor (String, Boolean)可以自動判斷沒檔案就新增,有檔案就加在後面,所以不用自己判斷了。

話說我後來找到一個非同步檔案 I/O,不曉得能不能解這種問題就是....


2012/08/16 update

之前壓力測試時,因為在本機測試,每秒跑不到100次,所以用之前的方式就可以避掉file lock的問題,後來搬到測試機上測試,加上程式效能又調教過,變成每秒可以跑500~600次,這時候又遇到IOException的問題了,剛遇到時,試了一些方法,都還是會有問題,不然就是搞到Out of memory XD ,原本都已經在看非同步存取的方式能不能解了,沒想到昨天晚上打LOL之前,又找了一下幾種可能的解法,今天到公司一試,還真的解掉了這問題。
        private static readonly object LockFile = new object();
        public static void writeFile()
        {
            using (var fs = new FileStream(filePath,FileMode.Append,FileAccess.Write,FileShare.ReadWrite))
            {
                using (var log = new StreamWriter(fs))
                {
                    lock (LockFile)
                    {
                        log.WriteLine(logtxt);
                    }
                }
            }
        }
說穿了也就只是用FileStream設定正確的FileShare權限而已,沒想到這麼簡單就解決了 -_-

在找解法的時候,也試過3rd party 的logging方式,如 NLog、log4net ,但是效能都會被拖到剩下1/3不到,只剩每秒不到200次,後來還是回頭自己寫效率比較好。

Jmeter2

而IOException在目前的測試下是還沒有發生過,速度也不會慢很多,所以這解法暫時是可以work的,等壓力測試能跑到更高的數值的時候,再看看有沒有需要改吧。

1 comment:

  1. I bought a Moncler down jacket for my boyfriend at this online store. replica MONCLER jacket sale mensThe quality is very good, best luxe Moncler Jacketthe style of the down jacket is very like, it is worth buying, value for money

    ReplyDelete

Related Posts Plugin for WordPress, Blogger...