是平行的.Foreach是提高代码执行速度的最佳方法
本文关键字:方法 执行 速度 代码 最佳 Foreach 高代码 | 更新日期: 2023-09-27 18:03:05
我有代码,我需要重写,以提高执行原始代码的速度:
数据类:
public class Data
{
public string Id {get;set;}
... Other properties
}
服务:(多于2个,例如我只给你2个)
public class SomeService1
{
public Result Process(Data data)
{
//Load data from different services hire
}
}
public class SomeService2
{
public Result Process(Data data)
{
//Load data from different services hire
}
}
实际方法
public void Calculate (List<Data> datas)
{
Result result;
SomeService1 someService1 = new SomeService1();
SomeService2 someService2 = new SomeService2();
// In this place list of data have about 2000 elements
foreach(var data in datas)
{
switch(data.Id)
{
case 1:
result = someService1.Process(data)
break;
case 2:
result = someService2.Process(data)
break;
default:
result = null;
}
ProcesAndSaveDataToDatabase(result);
}
}
方法Calculate
i将List作为此列表中每个元素的参数,它从外部服务(服务由data类中的id确定)获取数据。然后处理这些数据并保存到数据库中。对于2000个元素,整个操作时间约为8分钟,70%的时间用于从外部服务收集数据。我必须改变那个时间。我只有一个想法,但说实话,我不能用数据来测试它,因为只有数据在生产环境中(在生产环境中测试是坏主意)。我有一个主意。你能帮我看一下,给我指点一下方向吗?
数据类:
public class Data
{
public string Id {get;set;}
... Other properties
}
服务:(多于2个,例如我只给你2个)
public class SomeService1 : IService
{
public Result Process(Data data)
{
//Load data from different services hire
}
}
public class SomeService2 : IService
{
public Result Process(Data data)
{
//Load data from different services hire
}
}
IService:
public interface IService
{
Result Process(Data data);
}
实际方法:
Public void Calculate (List<Data> datas)
{
var split= from data in datas group data by data.Id into newDatas select newDatas
// Different list split by Id
Parallel.Foreach(split, new ParallelOptions{MaxDegreeOfParallelism = 4}, datas =>
{
Result result;
IService service = GetService(datas.FirsOfDefault().Id);
if(service == null) return;
foreach(var data in datas)
{
result = service.Process(data)
ProcesAndSaveDataToDatabase(result);
}
});
}
private IService GetService(string id)
{
IService service = null;
if(id == null ) return service;
switch(id)
{
case 1:
service = new SomeService1();
break;
case 2:
service = new SomeService2();
break;
}
return service;
}
在这个想法中,我尝试将不同的服务数据拆分到不同的线程中。因此,在列表中,我们将有Id = 1
的20个项目和Id = 2
的10个项目,它应该创建2个独立的线程并分别处理它,这应该允许我切断执行时间。这是一个好方法吗?还有其他改进代码的方法吗?谢谢
Parallel ForEach有助于改善CPU绑定任务,但您上面提到您正在并行调用IO绑定的服务。当你做IO绑定工作时(比如调用外部服务),你最好使用async和await而不是并行foreach。
Parallel ForEach将启动多个线程并阻塞这些线程,直到工作完成(所有线程阻塞大约8分钟)。
Async和Await将在服务调用之间编织工作线程,并有效地使用IO完成端口回调到应用程序。这避免了多线程阻塞,并允许您更有效地使用计算机资源。
关于如何进行并行异步调用的更多信息在这里:
https://msdn.microsoft.com/en-us/library/mt674880.aspx虽然在应用程序中使用Parallelism(Parallel.ForEach)可以获得好处,但这并不是提高代码执行速度的唯一方法。
同样,由于你在应用程序中使用LINQ,并且你可能也会广泛使用它,你可能很想在任何可能的地方使用PLINQ(并行LINQ)。
我还建议您尝试分析代码,以确定应用程序中的热点和瓶颈,这可能会让您更好地了解在哪里以及如何提高性能。 此外,正如Patrick所提到的,你应该尽可能尝试使用async和await。查看来自MSDN的这篇文章,它会给你更多的见解https://msdn.microsoft.com/en-us/library/ff963552.aspx