實現高性能穩定的socket tcp通訊經驗分享


    其實在.net socket編寫高性能穩定方面的資料真的比較少,一個實質性的測試數據結果對比就更少了.我們可以從http://msdn.microsoft.com/zh-cn/magazine/cc163356.aspx看到MS說net 2.0 sp1后的socket通訊能力非常強勁,可以同時掛起6W個IO(可以簡單地認為可以在一秒內send+receive可以達到6W或更高),但要找這個數據的測試似乎很難.但在一篇MS關於WCF的性能測試中基於tcp部署的性能在一台4路服務器中可以達到這個量(http://msdn.microsoft.com/en-us/library/bb310550.aspx).那WCF可以達到那基於c# socket實現達到這樣的IO處理能力應該完成沒問題.經常一段時間的努力即使在一台core e4300 5年前的PC上完全勝任每秒6W IO的處理能力,還包括數據接收,協議分析對像序列化寫入.

以下是一些經驗總結:

Buffer Pool

這個相信不用說,MSDN上也介紹這種用法.但如何分配這個buffer大小呢?我們一般會一條消息用一個buffer,這個時候我們就很難分配了,不得不按最大消息長度來定義buffer長度,這樣做從內存分配上來說是極其不合理的.不過現在內存多不用計較(也許).但還存在一種問題就是send的時候一般針對buffer的,當消息小的時候就不得不按消息的數量來操作IO,如果buffer的靈活性更好如小的消息可以多個寫入一個buffer,大的消息可以寫入幾個buffer.這樣即能達到內存使用合理.也能控制最少的IO處理最多的信息達到更好的性能.

SocketAsyncEventArgs池需要嗎?

這個MSDN上也有介紹這種用法,但就存在一個如何分配的問題,連接產生的時候分配,連接斷開的時候回收?如果是這個SAEA怎樣分配buffer大小(別輕易地使用SetBuffer(byte[],int,int)方法);不得不面對以上Buffer說的問題.所以SEAE和Buffer Pool一樣大小來分配池結合使用,用的時候拿用完回收到池. 其實SEAE最好是和BUFFER整合在一起,這樣做的好處就是在高並發的時候可以節省大量的byte[] Copy.

隊列的使用

  隊列的使用就是更好控制線程處理數據,既然一個線程就能更好地完成工作,可必要用更多的線程去做呢.記住用最少的線程完成最多的事情.

在運行期內你能做到最少化內存分配嗎?

  你能讓一些getByes方法不產生new byte[]嗎?好好看下MSDN相關對像方法看有什么途徑來達到這種效果.

不於過於自信多用些分析工具

  也許你有着很多年的經驗,也用一些計時器來衡量過代碼的執行行性能.但有時候你真的很難發現原來性能並不存在於你測的地方.不要只關注於代碼的CPU執行時間,別忘了.NET下還有一個巨頭GC.用性能分析工具分析代碼的執行時間同時,不要忘了分析一下代碼在某些情況下的內存分配情況.VS2010就提供了這些方便的分析工具.

以下是這段時間優化的測試情況

測試結果一:

1K連接分別獲取一個對像和一個列表對像

單一對像信息

class GetResponse : IMessage
    {
        public User User;

        public void Save(BufferWriter writer)
      
    }
    class User : IMessage
    {
        public string Name;
        public string EMail;
        public string City;
        public string Counrty;
        public void Save(BufferWriter writer)
        {
            writer.Write(Name);
            writer.Write(EMail);
            writer.Write(City);
            writer.Write(Counrty);
        }
        public void Load(BufferReader reader)
        {
            Name = reader.ReadString();
            EMail = reader.ReadString();
            City = reader.ReadString();
            Counrty = reader.ReadString();
        }
    }

列表對像信息(5條)

class Response : IMessage
    {
        private IList<Order> mOrders = new List<Order>();
        public IList<Order> Orders
        {
            get
            {
                return mOrders;
            }
        }
    }
    class Order : IMessage
    {
        public int OrderID;
        public string CustomerID;
        public int EmployeeID;
        public long OrderDate;
        public long RequiredDate;
        public string ShipName;
        public string ShipAddress;
        public string ShipCity;
        public string ShipRegion;
        public string ShipPostalCode;
        public string ShipCountry;
        public void Save(BufferWriter writer)
        {
            writer.Write(OrderID);
            writer.Write(CustomerID);
            writer.Write(EmployeeID);
            writer.Write(OrderDate);
            writer.Write(RequiredDate);
            writer.Write(ShipName);
            writer.Write(ShipAddress);
            writer.Write(ShipCity);
            writer.Write(ShipRegion);
            writer.Write(ShipPostalCode);
            writer.Write(ShipCountry);
        }
        public void Load(BufferReader reader)
        {
            OrderID = reader.ReadInt32();
            CustomerID = reader.ReadString();
            EmployeeID = reader.ReadInt32();
            OrderDate = reader.ReadInt64();
            RequiredDate = reader.ReadInt64();
            ShipName = reader.ReadString();
            ShipAddress = reader.ReadString();
            ShipCity = reader.ReadString();
            ShipRegion = reader.ReadString();
            ShipPostalCode = reader.ReadString();
            ShipCountry = reader.ReadString();
        }
    }

測試結果

測試結果2:

由於局域網帶寬限制,所以只能測試2K和3K連接下的單一對象獲取

除了以上測試結果外,還進行了同場景500物體狀態變更廣播,在core e4300也完全能勝任,每秒轉發50W的消息量.每個client的消息延時在100ms以內.

同場景物體廣播測試程序:http://www.henryfan.net/file.axd?file=2012%2f3%2fBroadcastTest.rar (想測試效果請分開電腦運行,如果你的網絡是100mb的話最大只能運行5個client,如果服務器的cpu低於core e4300也有可能支持不了500同屏)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM