Java ScheduledExecutorService - нужен совет по проблеме производительности в реальном времени - PullRequest
2 голосов
/ 03 февраля 2012

У меня есть созданное многопоточное приложение, которое выполняет разные задачи с тем же ScheduledExecutorService (метод scheduleAtFixedRate и фиксированный пул потоков из 10 потоков).Однако все потоки, кроме одной основной задачи (не путать с основной веткой!), Большую часть времени спят, пока не поступит пользовательский ввод.Данные, которые разделяются между основной задачей и другими потоками (пользовательский ввод), защищены объектами блокировки в синхронизированных блоках.

Основная задача выполняет задачу повторного восстановления с довольно большой частотой, скажем, 25 Гц (т.е. период 40 мс), и важно, чтобы эта задача была выполнена своевременно.Обычно это тоже так, но, к сожалению, не всегда.Другие «хорошие» приложения также работают на том же компьютере (Linux OP), но ЦП << 100%. </p>

В течение 60 минут измерения (т. Е. 90000 выборок) фактический период между двумя последовательными выборками был> =60 мс в 50 случаях, и примерно в 30 из них период составлял более 100 мс, в паре действительно плохих случаев (довольно близко друг к другу по времени, порядка секунд) период составлял от 1000 до 2300Миз.Пользовательский ввод не был сделан во время измерения.Глядя на журналы данных, кажется очевидным, что что-то мешает исполнителю выполнять свою работу в течение этих интервалов, поскольку за ними часто следует «догоняющее» Исполнителя, то есть несколько журналов из приложения в течение 2 или 3 мс.

Я пробовал периодически собирать мусор при каждом выполнении задачи, но (по крайней мере, в краткосрочной перспективе) это только ухудшает ситуацию.Я также измерил время выполнения задачи.Это в основном около 1 мс, и это не должно привести к поломке Исполнителя (или это должно быть?).Здесь также есть отклонения, иногда порядка 100 мс, но они объясняют менее 50% задержек.Я пытался найти TaskRejectedExceptions, ничего не нашел.

Итак, мои вопросы сейчас в основном: что я могу ожидать от ScheduledExecutorService с течением времени?Может ли это быть проблемой с потоком, несмотря на то, что в этих обстоятельствах должна выполняться только основная задача?Что может привести к тому, что ScheduledExecutor временно прекратит выполнение, а только заполнит журналы своими «догоняющими» данными, и есть ли какой-нибудь способ контролировать это раздражающее поведение?Может ли это быть связано с тем, что моя JVM - это просто обычная JVM без возможностей приоритета в реальном времени?Любая помощь, идеи или теории о том, где начать копать, действительно ценятся!

Ответы [ 2 ]

0 голосов
/ 03 февраля 2012

Несколько замечаний:

  • Вызов сборщика мусора не гарантирует сборку, как вы думаете.Из документа Java:

Вызов этого метода предполагает, что виртуальная машина Java затрачивает усилия на утилизацию неиспользуемых объектов, чтобы освободить доступную в настоящее время память для быстрого повторного использования.

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

  • Потоки запланированы, но их выполнение еще не запланировано.Если ваш процессор загружен менее чем на 100%, это не означает, что он может выполнять другой поток.В общем, ожидание очень точного выполнения потоков в реальном времени в среде, которую вы не писали полностью с нуля, вероятно, не приведет к желаемым результатам.
0 голосов
/ 03 февраля 2012

Согласно документации по таймеру , ваша ситуация выглядит совершенно нормально:

При выполнении с фиксированной скоростью каждое выполнение планируется относительно запланированного времени выполнения первоначального выполнения. Если выполнение по какой-либо причине задерживается (например, сборка мусора или другие фоновые действия), два или более выполнения будут выполняться в быстрой последовательности, чтобы «догнать». В долгосрочной перспективе частота выполнения будет точно равна обратной величине указанного периода (при условии, что системные часы, лежащие в основе Object.wait (long), точны).

Дело в том, что scheduleAtFixedRate () не может гарантировать, что выполнение начнется именно тогда, когда это должно начаться, а только частоту в долгосрочной перспективе. На самом деле, я не уверен, есть ли способ сделать это с помощью Java.

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