Моя команда работает над решением для встроенного Linux для продукта, в котором центральное приложение получает и обрабатывает данные от оборудования и отправляет их в базу данных и в интерфейсное приложение. При этом мы работаем с пятью потоками:
Это приложение не может пропустить ни одного пакета данных, поступающего от потока UPP, который получает новые данные каждые 200 мс. Поток DSP обычно занимает менее 200 мс (сейчас это занимает ~ 30 мс, но в будущем это займет больше времени). Поток БД вызывается нормально один раз каждые 30 с, а поток интерфейса вызывается с частотой 5 Гц.
Проблема, с которой мы сталкиваемся, заключается в том, что время от времени потоки занимают больше времени для выполнения своей работы, особенно потоки DB и DSP. IOW, хотя система работает с прогоном DSP на каждый прогон UPP, иногда UPP запускается до 15 раз без какого-либо вызова DSP, что приводит к потере полученных данных. Эти спорадические «лаги» в потоках возникают во всех из них, но лаги в БД и интерфейсе не являются проблематичными, только когда они возникают в потоках UPP или DSP.
Мы проверяем все, что можем, чтобы попытаться найти в нашем коде, где проблема лежит без успеха — большую часть времени система работает без каких-либо задержек. Мы заметили некоторые закономерности:
Мы начинаем думать, что это что-то с Linux. Обычно при повседневном использовании ПК возникают задержки с мышью или приложениями, и Linux может поступать так же с нами. Мы также подумали об использовании оперативной памяти, разделяемой между основным процессором Omap L138 и процессором DSP, но некоторые тесты дали отрицательное подтверждение этой гипотезе.
У вас есть какие-нибудь предложения? Может ли Linux действительно быть источником проблемы? Как мы можем знать и как мы можем исправить?
Любая помощь будет оценена.
P .: То же, что и этот
Это, вероятно, немного слишком просто, но это контрольный список вещей, которые я рассмотрел, когда имел дело с ошибками, которые касались времени и дизайна в прошлом.
Укажите, что такое приемлемое отставание
В случае чувствительных ко времени приложений преждевременная оптимизация может быть чрезвычайно дорогой, убедитесь, что вы понимаете, каковы ваши требования по задержке (имеют жесткие цифры), измеряете то, что вы наблюдаете, и продолжаете улучшаться, пока не достигнете своей цели.
Выберите подходящее оборудование
Убедитесь, что если у вас есть N темы, которые вы хотите разумные сроки, для которых у вас есть о N сердечники. Это позволяет легко доказать, что ваш процесс использует процессор. Даже если вы не можете сделать это в производственной среде, выполнение этого во время тестирования может помочь исключить некоторые типы ошибок.
Убедитесь, что ваше приложение не использует пространство подкачки — убедитесь, что у вас более чем достаточно оперативной памяти для всех возможных вариантов использования и времени выполнения. Используйте такой инструмент, как Valgrind чтобы убедиться, что у вас нет утечки памяти.
Выберите подходящий встроенный Linux
Чем критичнее время для вашего приложения, тем больше вероятность того, что вам понадобится операционная система, которая предлагает гарантии синхронизации. Работа на настоящей жесткой операционной системе реального времени даст совсем другие результаты, чем запуск на чем-то, что является просто урезанным настольным Linux. Знать и понимать значение встроенного Linux, который вы выбрали.
Выберите подходящий уровень приоритета для вашего приложения
Если вы видите спорадические лаги, убедитесь, что в вашей системе больше ничего не работает, что могло бы вызвать проблему. Я видел несколько странных вещей в настольных вариантах Linux, которые могут вызывать проблемы, в том числе аудио драйверы.
По крайней мере, во время тестирования повышайте свой приоритет, чтобы он был намного выше (меньшее значение), чем другие фоновые процессы. Ты можешь использовать отлично сделать это.
Понять, где происходят ваши вызовы ядра
Как указано в комментариях, использование такого инструмента, как Трассирование определить, какие вызовы ядра выполняются, очень хорошая идея. Точно так же некоторое понимание того, какие типы функции / операции инициирование системного вызова может быть очень полезным (например, по возможности, повторно использовать буферы, а не запускать частые выделения и освобождения).
Это также приводит к пониманию и минимизации блокировки, выполняемой вашим приложением. Это включает в себя очевидные вещи, такие как получение блокировок в согласованном порядке и минимизация времени, затрачиваемого на использование блокировок, а также использование простейших весовых примитивов синхронизации, которые имеют смысл (можете ли вы использовать атомику вместо мьютексов?).
Выберите подходящий планировщик и приоритеты потоков
Если у вас больше задач, чем ядер, подумайте, какой планировщик вы используете.
Планировщики общего назначения (в большинстве случаев) не подходят для приложений, критичных к производительности. Ваш дистрибутив Linux предоставит некоторый механизм для изменения планировщик (хотя это может потребовать повышения привилегий).
Круглое планирование (SCHED_RR) — хорошее начало, потому что оно позволяет довольно легко вычислить математику использования ЦП (по крайней мере, для приблизительной оценки). Убедитесь, что потоки с самыми жесткими временными требованиями имеют самый высокий приоритет. Имейте в виду, что изменение приоритетов может вызвать некоторые тонкие ошибки (инверсия приоритетов)
Зафиксируйте критические потоки производительности для определенных ядер
Это можно сделать с помощью вызова операционной системы (или платформы), чтобы установить привязку потока (необходимость оставаться на определенном ядре). sched_affinity. В некоторых случаях это может помочь обеспечить постоянную производительность кеша