实现高性能稳定的socket tcp通讯经验分享
? ? 其實在.net socket編寫高性能穩(wěn)定方面的資料真的比較少,一個實質(zhì)性的測試數(shù)據(jù)結(jié)果對比就更少了.我們可以從http://msdn.microsoft.com/zh-cn/magazine/cc163356.aspx看到MS說net 2.0 sp1后的socket通訊能力非常強勁,可以同時掛起6W個IO(可以簡單地認為可以在一秒內(nèi)send+receive可以達到6W或更高),但要找這個數(shù)據(jù)的測試似乎很難.但在一篇MS關于WCF的性能測試中基于tcp部署的性能在一臺4路服務器中可以達到這個量(http://msdn.microsoft.com/en-us/library/bb310550.aspx).那WCF可以達到那基于c#?socket實現(xiàn)達到這樣的IO處理能力應該完成沒問題.經(jīng)常一段時間的努力即使在一臺core e4300 5年前的PC上完全勝任每秒6W IO的處理能力,還包括數(shù)據(jù)接收,協(xié)議分析對像序列化寫入.
以下是一些經(jīng)驗總結(jié):
Buffer Pool
這個相信不用說,MSDN上也介紹這種用法.但如何分配這個buffer大小呢?我們一般會一條消息用一個buffer,這個時候我們就很難分配了,不得不按最大消息長度來定義buffer長度,這樣做從內(nèi)存分配上來說是極其不合理的.不過現(xiàn)在內(nèi)存多不用計較(也許).但還存在一種問題就是send的時候一般針對buffer的,當消息小的時候就不得不按消息的數(shù)量來操作IO,如果buffer的靈活性更好如小的消息可以多個寫入一個buffer,大的消息可以寫入幾個buffer.這樣即能達到內(nèi)存使用合理.也能控制最少的IO處理最多的信息達到更好的性能.
SocketAsyncEventArgs池需要嗎?
這個MSDN上也有介紹這種用法,但就存在一個如何分配的問題,連接產(chǎn)生的時候分配,連接斷開的時候回收?如果是這個SAEA怎樣分配buffer大小(別輕易地使用SetBuffer(byte[],int,int)方法);不得不面對以上Buffer說的問題.所以SEAE和Buffer Pool一樣大小來分配池結(jié)合使用,用的時候拿用完回收到池. 其實SEAE最好是和BUFFER整合在一起,這樣做的好處就是在高并發(fā)的時候可以節(jié)省大量的byte[] Copy.
隊列的使用
隊列的使用就是更好控制線程處理數(shù)據(jù),既然一個線程就能更好地完成工作,可必要用更多的線程去做呢.記住用最少的線程完成最多的事情.
在運行期內(nèi)你能做到最少化內(nèi)存分配嗎?
你能讓一些getByes方法不產(chǎn)生new byte[]嗎?好好看下MSDN相關對像方法看有什么途徑來達到這種效果.
不于過于自信多用些分析工具
也許你有著很多年的經(jīng)驗,也用一些計時器來衡量過代碼的執(zhí)行行性能.但有時候你真的很難發(fā)現(xiàn)原來性能并不存在于你測的地方.不要只關注于代碼的CPU執(zhí)行時間,別忘了.NET下還有一個巨頭GC.用性能分析工具分析代碼的執(zhí)行時間同時,不要忘了分析一下代碼在某些情況下的內(nèi)存分配情況.VS2010就提供了這些方便的分析工具.
以下是這段時間優(yōu)化的測試情況
測試結(jié)果一:
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();}}測試結(jié)果
測試結(jié)果2:
由于局域網(wǎng)帶寬限制,所以只能測試2K和3K連接下的單一對象獲取
除了以上測試結(jié)果外,還進行了同場景500物體狀態(tài)變更廣播,在core e4300也完全能勝任,每秒轉(zhuǎn)發(fā)50W的消息量.每個client的消息延時在100ms以內(nèi).
同場景物體廣播測試程序:http://www.henryfan.net/file.axd?file=2012%2f3%2fBroadcastTest.rar (想測試效果請分開電腦運行,如果你的網(wǎng)絡是100mb的話最大只能運行5個client,如果服務器的cpu低于core e4300也有可能支持不了500同屏)
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的实现高性能稳定的socket tcp通讯经验分享的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Visual Studio 2012 简
- 下一篇: ×××网络连接安全性以及协议支持介绍