C # Отключить сборку мусора для USB ReadPipe - PullRequest
0 голосов
/ 23 октября 2018

Я пытаюсь собрать данные с USB-порта, используя D3XX.NET из FTDI.Данные собираются и затем отправляются в быстрое преобразование Фурье для построения спектра.Это прекрасно работает, даже если вы пропустите некоторые данные.Ты не можешь сказать.Однако, если вы затем захотите отправить эти данные на компонент вывода звука, вы заметите, что данные отсутствуют.Вот где моя проблема, кажется.Данные собираются и затем отправляются на аудиоустройство.Все пакеты делают это в течение необходимого промежутка времени.Тем не менее, звук сбрасывает данные, которые появляются.Вот изображение того, как синусоида выглядит на выходе аудио:

enter image description here

Вы можете видеть, что некоторые данные отсутствуют в началеи кажется, что целый цикл отсутствует в конце.Это только один пример, он постоянно меняется.Иногда кажется, что данных просто нет.Я прошел всю цепочку обработки, и я уверен, что пакеты данных для звука делают это.С тех пор я использовал профилировщик производительности JetBrains.Я обнаружил следующее: метод ReadPipe занимает 8,5 мс, что в точности соответствует ожидаемому чтению.Все идет нормально.Как только команда ReadPipe закончится, у вас есть 0,5 мс, чтобы сделать другую ReadPipe, или вы потеряете некоторые данные.Глядя на вывод профилировщика, я вижу это:

enter image description here

ReadPipe занимает 8,5 мс, а затем есть эта запись для сборки мусора, которая в среднем занимает 1,6 мс,Если это действительно происходит даже иногда, то я потерял некоторые данные.

Итак, вот код: Это фоновый работник:

    private void CollectData(object sender, DoWorkEventArgs e)
    {
        while (keepGoing)
        {
            ftStatus = d3xxDevice.ReadPipe(0x84, iqBuffer, 65536, ref bytesTransferred); //read IQ data - will get 1024 pairs - 2 bytes per value

            _waitForData.Set();
        }
    }

Ручка ожидания указывает другому потоку, что данныедоступен.Так GC является причиной потери данных?И если так, как я могу избежать этого?Спасибо!

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Если вы можете подтвердить, что у вас недостаточно памяти, попробуйте установить GCSettings.LatencyMode на GCLatencyMode.SustainedLowLatency.Это предотвратит некоторые блокирующие сборки мусора, если у вас недостаточно памяти.Ознакомьтесь с документами о режимах задержки для получения дополнительной информации и ограничений.

Если сборка мусора все еще слишком разрушительна для вашего варианта использования, и вы используете .NET 4.6 или более позднюю версию, возможно, выв состоянии попробовать позвонить GC.TryStartNoGCRegion .Этот метод попытается зарезервировать достаточно памяти, чтобы выделить до указанного количества, и заблокировать GC, пока вы не исчерпали резервирование.Если объем используемой памяти достаточно постоянен, вы можете избежать передачи достаточно большого значения, чтобы приспособить использование вашего приложения, но нет никакой гарантии, что вызов будет успешным.

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

Еще одна вещь, на которую следует обратить внимание, это то, что C # не совсем подходящий инструмент дляприложения, которые не могут терпеть сбои.Если вы знакомы с написанием нативного кода, вы можете выполнять чувствительную ко времени работу в неуправляемом потоке;Насколько мне известно, это единственное надежное решение, особенно если ваше приложение будет работать на компьютерах конечных пользователей.

0 голосов
/ 23 октября 2018

Вам нужно быть более дружелюбным по отношению к вашему сборщику мусора и не выделять так много.

Короче говоря, если ваш GC останавливает ваши потоки, у вас проблема с мусором.GC приостановит все потоки для очистки, и вы ничего не сможете сделать, кроме лучшего управления тем, какой мусор вы создаете.

Если у вас есть массивы, не создавайте их постоянно, вместо этого используйте повторноих (так далее и так далее).Используйте более легкие конструкции, используйте инструменты, которые позволят вам сократить распределение, например Span<T> и Memory<T>.Подумайте об использовании less awaits, если ваш код сильно async, и не ставьте их в циклы.Пройдите мимо ref и используйте локальные ссылки и т. Д., Если это возможно, держитесь подальше от больших неуправляемых блоков данных.

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

...