Как я могу убедиться, что мои тесты запускаются и работают правильно? - PullRequest
0 голосов
/ 18 октября 2019

Я определяю между использованием блоков потока данных TPL или неким подходом производителя / потребителя для этих тестов. Создание списка задач будет очень быстрым, поскольку каждая задача будет просто строкой, содержащей список параметров тестирования, таких как параметры настройки, требуемые измерения и время между измерениями. Этот список задач будет просто файлом, загружаемым через графический интерфейс (1 файл на тест).

Когда тест запускается, он должен начинаться сразу же. Тесты могут быть очень длинными и очень асинхронными, так как действие может занять несколько секунд или десятков минут (например, нагрев устройства), после чего следует измерение, которое занимает несколько секунд (или минут), после чего следует длительный период бездействия (24 часа) перед повторным тестом.

У меня может быть до 16 тестов одновременно, но мне нужна гибкость, чтобы можно было отменить любой из этих тестов в любое время. Мне также нужно иметь возможность ДОБАВИТЬ новый тест в любое время (т. Е. Попытаться изобразить тестирование 16 устройств или промежуток месяца, в течение которого отдельные тестовые устройства добавляются и удаляются в течение месяца).

(Visual C #) Я попробовал этот пример кода для потока данных TPL, где я говорю, чтобы он одновременно выполнял 32 простые задачи. Каждое задание задерживается на 5 секунд для имитации работы. Похоже, что задачи обрабатываются параллельно, так как время выполнения задач заняло 15 секунд. Я предполагаю, что все 32 задачи не были завершены в течение 5 секунд из-за планирования и других накладных расходов, но я немного беспокоюсь, что некоторые задачи могут быть заблокированы.

    class Program
    {
    // Performs several computations by using dataflow and returns the elapsed
    // time required to perform the computations.
    static TimeSpan TimeDataflowComputations(int messageCount)
    {
    // Create an ActionBlock<int> that performs some work.
    var workerBlock = new ActionBlock<int>(
        // Simulate work by suspending the current thread.

        millisecondsTimeout => Thread.Sleep(millisecondsTimeout),
       // Specify a maximum degree of parallelism.
       new ExecutionDataflowBlockOptions
       {
           MaxDegreeOfParallelism = messageCount
       });


    // Compute the time that it takes for several messages to 
    // flow through the dataflow block.

    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();

    for (int i = 0; i < messageCount; i++)
    {
        workerBlock.Post(5000);  // simulated work: a delay of 5 seconds.
    }
    workerBlock.Complete();

    // Wait for all messages to propagate through the network.
    workerBlock.Completion.Wait();

    // Stop the timer and return the elapsed number of milliseconds.
    stopwatch.Stop();
    return stopwatch.Elapsed;
    }



    static void Main(string[] args)
    {

    int messageCount = 32; 

    TimeSpan elapsed;

    // set processors  maximum degree of parallelism. This causes
    // multiple messages to be processed in parallel.

    Console.WriteLine("START:\r\n");
    elapsed = TimeDataflowComputations(messageCount);
    Console.WriteLine("message count = {1}; " +
       "elapsed time = {2}ms.", messageCount, 
        (int)elapsed.TotalMilliseconds);

    Console.ReadLine();
    } 
    }

Демонстрация, кажется, работает, но яЯ не уверен, была ли заблокирована какая-либо из задач до тех пор, пока одна или несколько из 5-секундных задач не были выполнены. Я также не уверен, как можно идентифицировать каждый блок действий, чтобы отменить определенный.

1 Ответ

3 голосов
/ 18 октября 2019

Причина, по которой вы не получаете ожидаемую производительность, заключается в том, что ваша рабочая нагрузка является синхронной и блокирует потоки пула потоков. Ожидаете ли вы на самом деле синхронной (блокирующей) рабочей нагрузки в вашей производственной среде? Если да, вы можете попробовать увеличить резерв доступных потоков ThreadPool перед запуском конвейера потока данных TPL:

ThreadPool.SetMinThreads(workerThreads: 100, completionPortThreads: 100);

Если ваша фактическая рабочая нагрузка асинхронная, то лучше смоделировать ее с помощью Task.Delay вместоThread.Sleep.

var workerBlock = new ActionBlock<int>(async millisecondsTimeout =>
{
    await Task.Delay(millisecondsTimeout);
}, new ExecutionDataflowBlockOptions
{
    MaxDegreeOfParallelism = messageCount
});

Я не проверял это, но вы должны получить время завершения около 5 секунд с обоими этими подходами.

...