C# 百分求助,关于UDP发送速度的提高,遇到效率瓶颈了无法突破。

dqvega 2012-08-31 04:51:55
公司要求写一个UDP数据源的工具,用来发送一种特定的包格式,要求发包速率达到20M/S,每个包大小1500byte即不能分片。
也就是说每秒发包要达到大概 14000次/秒。
目前我想尽了一切办法,最高也只能达到每秒3000多次,速率在5M/s左右。。。

简略代码如下


private void Btn_Start_Click(object sender, EventArgs e)
{
if (Btn_Start.Text == "发送")
{
Btn_Start.Text = "停止";
SendStatusLabel.Text = ("发送成功!");
Config_groupBox.Enabled = false;
File_groupBox.Enabled = false;
//Statistics_groupBox.Enabled = false;

try
{
UdpDataSend = new Thread(new ThreadStart(DataSend));
UdpDataSend.Priority = ThreadPriority.Normal;
UdpDataSend.IsBackground = true;
UdpDataSend.Start(); ////////////////////////这里起一个线程用来发包

timer = new System.Timers.Timer(TimeBlank);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();///////////////////////////////这个timer是用来统计流量的
}
catch (Exception ex) { throw ex; }
}
else if (Btn_Start.Text == "停止")
{
Btn_Start.Text = "发送";
SendStatusLabel.Text = ("发送已停止!");
Config_groupBox.Enabled = true;
File_groupBox.Enabled = true;
//Statistics_groupBox.Enabled = true;

UdpDataSend.Abort();

}
}

int LoopCount = 0;
byte[] Msg_DataPackage = null;
Socket udpclient_Socket;
UdpClient udpclient;
IPEndPoint ipEndPoint;
///////////////////////////////////////发包的函数,从我的表格里读取参数,表格一行代表一个包的参数,所以每次循///////////////////////////////////////环表有多少行就发多少个包
private void DataSend2()
{
lock (this)
{
while (Thread.CurrentThread.ThreadState.Equals(ThreadState.Background))
{
LoopCount++;
for (int i = 0; i < UDP_Table.RowCount; i++)
{
if (udpclient != null)
{
udpclient.Release();
}
BitJudge(tableModel.Rows[i].Cells[3].Text, out BitArray);
if (BitArray[5] == true)
{
/////////////第一种udpclient的方式,直接用send同步发送或者用BeginSend异步发送
//ipEndPoint = new IPEndPoint(IPAddress.Parse(tableModel.Rows[i].Cells[7].Text), Convert.ToInt32(tableModel.Rows[i].Cells[8].Text));
//udpclient = new UdpClient(LocalPort);

/////////////第二种socket的方式SocketType可用Dgram或者Ram
udpclient_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Udp);
IPAddress remoteIp = IPAddress.Parse(tableModel.Rows[i].Cells[7].Text);

////////////组包函数
Msg_SourceData(tableModel.Rows[i].Cells[1].Text,
Convert.ToInt32(tableModel.Rows[i].Cells[2].Text),
tableModel.Rows[i].Cells[3].Text,
tableModel.Rows[i].Cells[4].Text,
LoopCount,
tableModel.Rows[i].Cells[5].Text,
tableModel.Rows[i].Cells[6].Text,
tableModel.Rows[i].Cells[9].Text,
out Msg_DataPackage);


//////////////发送部分
//udpclient.Send(Msg_DataPackage, Msg_DataPackage.Length, ipEndPoint);
//udpclient.BeginSend(Msg_DataPackage, Msg_DataPackage.Length, ipEndPoint, new AsyncCallback(SendCallback), udpclient);
//udpclient.Close();

udpclient_Socket.SendTo(Msg_DataPackage, new IPEndPoint(remoteIp, LocalPort));
udpclient_Socket.Close();

AllPackageCount++;
AllSizeCount += Convert.ToUInt64(tableModel.Rows[i].Cells[2].Text) + 28;
}
}
}
}
}

/////////////////////updclient异步发送时的回调函数
public void SendCallback(IAsyncResult ar)
{
if (udp != null)
{
udp.Close();
}
}



目前的效率,用udpclient方式发包,同步方式,send,大概每秒1300多个包,速率1.96M/s
用异步方式BeginSend发包,大概每秒1500多个包,速率2.3M/s

用Socket发包,SocketType设为Dgram的时候和用udpclient异步发包时候差不多。但是用Ram的时候可以达到每秒3000多个包,速率5M多/s


即时如此,依然离要求很远啊。。20M/s,14000个包每秒。。。。。。。。每个包1500byte

其中组包函数要占用一定的时间,但是不是关键,去掉组包函数,直接new一个1500byte的空数组放在内存,每次发这个空数组,速度只能提升200个包每秒。效率瓶颈就在udp.send()这个地方


求各位大神多多指点。兄弟先谢谢了
...全文
1076 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
dqvega 2013-05-23
  • 打赏
  • 举报
回复
忘记回复了,当时最终解决了 首先得使用千M路由,当初测试用的百M路由。后来才反应过来换掉的 第二我测试的udpclient比socket快,所以用了udpclient,这里关于udpclient的new都要放在函数外,在函数内外效率差距很大。
njjxclh 2013-02-01
  • 打赏
  • 举报
回复
网络拥塞 解决了吗 ?
鸭梨山大帝 2013-02-01
  • 打赏
  • 举报
回复
调试查看,哪个部分最占用时间. "目前我想尽了一切办法,最高也只能达到每秒3000多次,速率在5M/s左右" 你在目标Server上查看到的吗? 还是非正式环境?
wwwww112233 2013-02-01
  • 打赏
  • 举报
回复
楼主,解决了吗
qldsrx 2012-08-31
  • 打赏
  • 举报
回复
请问你们公司使用的都是千兆网卡吗?百兆网卡的最高传输速率是100/8=12M/s,要达到20M/s只能是千兆网卡,另外要考虑丢包重传的话,速度更受到影响。

另外磁盘I/O也有影响,除非不读写磁盘,否则按照1M的磁盘读写缓存来计算,平均20M/s这个数字要达到也比较吃力,至少老的磁盘不能胜任。
showjim 2012-08-31
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
I5 2320的CPU,xp系统,我试过多线程,一个线程发1-10的包,一个线程发11-20的包,似乎速率没有提升。。。不知道是不是用错了,C#我才用了几个月还不熟。
另外,组包函数中要读文件,所以只能每个线程分别发送不同的包,不然都去读一个文件就的加锁,那速度就没什么区别了。
“另外简化发送函数中的代码,一些费时的操作看看能不能提前处理掉”我晚上回去想想办法,主要就是发包函数的简化,不过这里真不能提升多少性能,我用空数据包直接new到内存里每次发包读内存,不运行我的发包函数,只能提升200个包/s
[/Quote]
一个文件?我觉得你的情况,最终总瓶颈应该是读文件,而不是网络。
可以尝试一个线程读文件,X(小于CPU核心数量)个线程处理数据生成网络包,N个线程同步或者异步发包。
线程数以跟上文件操作为标准,最好实现动态调整。
dqvega 2012-08-31
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

单单靠代码是有限的,还要提高你机器性能,比如cpu数量,专业可以并发 运行多个线程,如果你每个线程能发5000个包,那么4核cpu跑4个线程,就是2w个包,另外简化发送函数中的代码,一些费时的操作看看能不能提前处理掉
[/Quote]

I5 2320的CPU,xp系统,我试过多线程,一个线程发1-10的包,一个线程发11-20的包,似乎速率没有提升。。。不知道是不是用错了,C#我才用了几个月还不熟。
另外,组包函数中要读文件,所以只能每个线程分别发送不同的包,不然都去读一个文件就的加锁,那速度就没什么区别了。
“另外简化发送函数中的代码,一些费时的操作看看能不能提前处理掉”我晚上回去想想办法,主要就是发包函数的简化,不过这里真不能提升多少性能,我用空数据包直接new到内存里每次发包读内存,不运行我的发包函数,只能提升200个包/s
dqvega 2012-08-31
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

单单靠代码是有限的,还要提高你机器性能,比如cpu数量,专业可以并发 运行多个线程,如果你每个线程能发5000个包,那么4核cpu跑4个线程,就是2w个包,另外简化发送函数中的代码,一些费时的操作看看能不能提前处理掉
[/Quote]

I5 2320的CPU,xp系统,我试过多线程,一个线程发1-10的包,一个线程发11-20的包,似乎速率没有提升。。。不知道是不是用错了,C#我才用了几个月还不熟。
另外,组包函数中要读文件,所以只能每个线程分别发送不同的包,不然都去读一个文件就的加锁,那速度就没什么区别了。
“另外简化发送函数中的代码,一些费时的操作看看能不能提前处理掉”我晚上回去想想办法,主要就是发包函数的简化,不过这里真不能提升多少性能,我用空数据包直接new到内存里每次发包读内存,不运行我的发包函数,只能提升200个包/s
dqvega 2012-08-31
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

数据读取与解析到底用了占用了总时间的百分之多少?公用Socket比每次new好多少?
楼主可以还尝试两个方向:两个线程会比一个线程好吗?异步会比同步好吗?
[/Quote]

我回去试试,估计“公用Socket比每次new好多少?”能让效率提高不少,刚刚才想起socket new的时候对效率有影响
C#我其实做了才几个月,以前一直做C得,所以我也不知道这种简单处理多线程是否比单线程好,异步是否比同步好这个我试验过了,udpclient方式异步确实更好,但是提升很小。socket的异步我暂时还不会用。。。。
bdmh 2012-08-31
  • 打赏
  • 举报
回复
单单靠代码是有限的,还要提高你机器性能,比如cpu数量,专业可以并发 运行多个线程,如果你每个线程能发5000个包,那么4核cpu跑4个线程,就是2w个包,另外简化发送函数中的代码,一些费时的操作看看能不能提前处理掉
SocketUpEx 2012-08-31
  • 打赏
  • 举报
回复
20M/S,每个包大小1500byte即不能分片。
也就是说每秒发包要达到大概 14000次/秒。

好厉害


showjim 2012-08-31
  • 打赏
  • 举报
回复
数据读取与解析到底用了占用了总时间的百分之多少?公用Socket比每次new好多少?
楼主可以还尝试两个方向:两个线程会比一个线程好吗?异步会比同步好吗?
缭绕飘渺 2012-08-31
  • 打赏
  • 举报
回复
真不懂
帮你顶
顺便等看解决方案

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧