【发布时间】:2018-04-05 22:20:55
【问题描述】:
我不擅长充分利用资源,因此我正在为需要并行且高效完成的任务寻找最佳方式。
我们有一个场景,我们必须 ping 数百万个系统并接收响应。响应本身不需要计算时间,但任务是基于网络的。
我当前的实现是这样的 -
Parallel.ForEach(list, ip =>
{
try
{
// var record = client.QueryAsync(ip);
var record = client.Query(ip);
results.Add(record);
}
catch (Exception)
{
failed.Add(ip);
}
});
我测试了这段代码
- 100 件商品大约需要 4 秒
- 1k 个项目大约需要 10 秒
- 10k 个项目大约需要 80 秒
- 100k 个项目大约需要 710 秒
我需要处理接近 20M 的查询,我应该使用什么策略来进一步加快速度
【问题讨论】:
-
警告:
results(和failed)如果是List<T>,则不是线程安全的。 -
是的,我使用 concurrentBag 但这只是加速的绝望措施,我将恢复为线程安全集合
-
如果
client.Query有异步版本,那么最好的方法是使用它,因为网络调用是 IO 任务。 -
这里列出了多个选项(数据流、自定义分区器、信号量苗条):stackoverflow.com/q/14673728/5311735。您需要使用
QueryAsync和一定程度的并行性,您应该以经验方式找到它们,例如 100,甚至可能是 1000。无限程度可能会或可能不会使您的套接字饱和,这取决于QueryAsync完成的速度和一些其他的东西,所以也值得尝试。请注意,只有当QueryAsync使用真正的异步 IO 而不是伪造它(通过Task.Run之类的东西)时,它才会起作用。 -
如果发生这种情况
QueryAsync不是真正的异步 - 请执行ThreadPool.SetMinThreads(100, 8)(其中 100 是您需要的并行度)并再次尝试任何解决方案。
标签: c# .net multithreading