是平行的.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个独立的线程并分别处理它,这应该允许我切断执行时间。这是一个好方法吗?还有其他改进代码的方法吗?

谢谢

是平行的.Foreach是提高代码执行速度的最佳方法

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所提到的,你应该尽可能尝试使用asyncawait

查看来自MSDN的这篇文章,它会给你更多的见解https://msdn.microsoft.com/en-us/library/ff963552.aspx