实现高性能稳定的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同屏)
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的实现高性能稳定的socket tcp通讯经验分享的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Visual Studio 2012 简
- 下一篇: Standard C Library -