Одновременно выполняется несколько задач C # - PullRequest
0 голосов
/ 16 мая 2018

У меня есть служба веб-API REST в IIS, которая принимает коллекцию объектов запроса.Пользователь может ввести более 100 объектов запроса.

Я хочу выполнить этот запрос 100 одновременно, а затем агрегировать результат и отправить его обратно.Это включает в себя как операции ввода-вывода (вызов внутренних служб для каждого запроса), так и операции с привязкой к процессору (для вычисления нескольких элементов ответа)

Фрагмент кода -

using System.Threading.Tasks;
....

var taskArray = new Task<FlightInformation>[multiFlightStatusRequest.FlightRequests.Count];

for (int i = 0; i < multiFlightStatusRequest.FlightRequests.Count; i++)
{
    var z = i;
    taskArray[z] = Tasks.Task.Run(() =>
        PerformLogic(multiFlightStatusRequest.FlightRequests[z],lite, fetchRouteByAnyLeg)
        );
}
Task.WaitAll(taskArray);
for (int i = 0; i < taskArray.Length; i++)
{
    flightInformations.Add(taskArray[i].Result);
}

public Object PerformLogic(Request,...)
{
    //multiple IO operations each depends on the outcome of the previous result
    //Computations after getting the result from all I/O operations
}

Если я по отдельности запускаюОперация PerformLogic (для 1 объекта) занимает 300 мс, теперь мое требование заключается в том, чтобы при выполнении этого PerformLogic () для 100 объектов в одном запросе это занимало около 2 секунд.

PerformLogic () имеет следующеешаги - 1. Позвоните в сторонний веб-сервис, чтобы получить некоторые детали. 2. На основе подробностей позвоните в другой сторонний веб-сервис. 3. Соберите результат из веб-сервиса, примените несколько преобразований

Но с Task.run ()это займет около 7 секунд, я хотел бы знать лучший подход для обработки параллелизма и достижения желаемого значения NFR в 2 секунды.Я могу видеть, что в любой момент времени 7-8 потоков работают одновременно

, но я не уверен, что если я смогу создать 100 потоков или задач, мы увидим лучшую производительность.Пожалуйста, предложите подход, чтобы справиться с этим эффективно.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Во-первых, не изобретай велосипед.PLINQ прекрасно справляется с параллельной работой, нет необходимости обрабатывать задачи вручную или объединять результаты.

Если вам нужно 100 задач, каждая из которых выполняется по 300 мс за 2 секунды, вам нужно как минимум 15 параллельных рабочих, игнорируя стоимость самого распараллеливания .

var results = multiFlightStatusRequest.FlightRequests
                                      .AsParallel()
                                      .WithDegreeOfParallelism(15) 
                                      .Select(flightRequest => PerformLogic(flightRequest, lite, fetchRouteByAnyLeg)
                                      .ToList();

Теперь вы сказали PLinq использовать 15 одновременно работающих рабочих для работы над очередью задач.Вы уверены, что ваша машина подходит для этой задачи?Вы можете поместить туда любое число, которое вам нужно, но это не значит, что ваш компьютер волшебным образом получает возможность сделать это.

Другой вариант - посмотреть на ваш метод PerformLogic и оптимизировать его.Вы называете это 100 раз, может быть, стоит оптимизировать.

0 голосов
/ 16 мая 2018

Судя по этому

public Object PerformLogic(Request,...)
{
  //multiple IO operations each depends on the outcome of the previous result
  //Computations after getting the result from all I/O operations
}

Держу пари, что PerformLogic проводит большую часть времени в ожидании операций ввода-вывода. Если это так, есть надежда с async. Вам придется переписать PerformLogic и, возможно, даже операции ввода-вывода - async должен присутствовать на всех уровнях, от верха до низа. Но если вы можете сделать это, результат должен быть намного быстрее.

Кроме этого - получите более быстрое оборудование. Если 8 ядер занимают 7 секунд, то получают 32 ядра. Это дорого, но все же может быть дешевле, чем переписать код.

...