Триггерный C# метод с различным временем обработки - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть метод c#, который периодически вызывается камерой. Событие вызова, как известно, очень точное. Камера работает на частоте 2500 Гц, поэтому этот метод следует вызывать каждые 400 микросекунд.
Вот упрощенная версия метода:

// Main class
private static List<double> T_Copy = new List<double>();
private static List<double> T_Call = new List<double>();
private static Stopwatch SW_Copy = new Stopwatch();
private static Stopwatch SW_Call = new Stopwatch();

void PeriodicalCalled()
{
    // (...) some other stuff inside a "if" condition which is not called for the sake of this test

    if (MyDLL.Flag)
    {
        // Elapsed time between method calls
        SW_Call.Stop();
        T_Call.Add(SW_Call.Elapsed.TotalMilliseconds);
        SW_Call.Restart();

        // Elapsed time to perform a copy
        SW_Copy.Restart();
        Buffer = new byte[4, 2560 * 3];
        SDK.GetBuffer(Buffer);
        MyDLL.CopyBuffer(Buffer);
        SW_Copy.Stop();
        T_Copy.Add(SW_Copy.Elapsed.TotalMilliseconds);
    }

    // This Flag is set once CopyBuffer has reached the end of its buffer size
    if (!MyDLL.Flag && T_Call.Count > 0)
    {
        string[] SaveText = new string[T_Call.Count];
        for (int i = 0; i < T_Call.Count; ++i) SaveText[i] = "Call; " + T_Call[i] + "; Copy; " + T_Copy[i];
        File.WriteAllLines("timeTest.txt", SaveText);
        T_Call.Clear();
        T_Copy.Clear();
    }
}

// Enables test
void SetFlag()
{
    MyDLL.Flag = true;
}

// MyDLL class
public static bool MyFlag = false;
private const int SIZE = 20000;
private static byte[][,] MyBuffer = new byte[SIZE][,];
private static int MyBufferIndex = 0;

public static void CopyBuffer(byte[,] Buffer)
{
    MyBuffer[MyBufferIndex] = Buffer;
    MyBufferIndex++;

    if (MyBufferIndex >= SIZE)
    {
        MyFlag = false;
        // Do work with filled MyBuffer
    }
}

Тест запускается путем вызова метода SetFlag (). Для каждого события, запускаемого SDK, я создаю новый пустой массив byte [,], который будет заполняться методом SDK.GetBuffer (). Затем я отправляю массив в MyDLL, который будет ссылаться на этот массив при следующем индексе MyBuffer.

Так что, как вы можете видеть, каждая итерация этого кода выполняет точно такую ​​же работу. Однако при просмотре файла timeTest.txt время, затрачиваемое на каждую итерацию, не одинаково.

Скажем, итерации 19900/20000 верны (значения T_Copy меньше 50 микросекунд, а значения T_Call близки к 400 микросекундам (+ - 5 микросекунд)).

Оставшиеся 100 итераций действительно занимают гораздо больше времени, до 10 миллисекунд, и случайным образом распределяются между 20000 итерациями. Всякий раз, когда это происходит, PeriodicalCalled () блокируется до тех пор, пока копирование буфера не будет завершено, и на следующей итерации T_Call будет содержать значение, немного превышающее 10 миллисекунд.

Вызов 0,4432 Копировать 0,0199

Звонок 0,3823 Копия 12,3993

Звонок 12,506 Копия 0,0094

Звонок 0,3878 Копия 0,0069

Звонок 0,3698 Копия 0,0069

  • Этот код запускается в отдельном потоке с Priority.Highest
  • Я посмотрел на использование памяти / процессора, и все выглядит нормально.
  • Я деактивировал несколько Windows сервисов (Защитник, Брандмауэр, Обновление), но ничего не изменил.

У вас есть идеи, почему производительность внезапно меняется?

Спасибо,

Редактировать:

Спасибо @germi за поиск причины проблемы. Я изменил следующий код:

// Enables test
void SetFlag()
{
    GC.TryStartNoGCRegion(SIZE * 4 * 2560 * 3);
    MyDLL.Flag = true;
}

public static void CopyBuffer(byte[,] Buffer)
{
    MyBuffer[MyBufferIndex] = Buffer;
    MyBufferIndex++;

    if (MyBufferIndex >= SIZE)
    {
        MyFlag = false;
        GC.EndNoGCRegion();
        // Do work with filled MyBuffer
    }
}

Единственное ограничение, которое это накладывает, состоит в том, что максимальный РАЗМЕР составляет около 8000 кадров, что по-прежнему составляет около 250 МБ памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...