Измерение загрузки контроллера можно условно разделить на:
- измерение нагрузки процессора. Показывает справляется ли вся система в целом: Windows + TwinCAT.
- Измерение времени исполнения программы в текущем цикле. Укладывается ли текущая ветвь программы в заданное время цикла.
- Профилирование. Замер времени выполнения отдельных частей программы.
И возвращаясь к теме предыдущего поста: "измерять производительность — это хороший способ узнать, осталось ли что-нибудь за кадром. Иногда это просто любопытство".
Разбор программы
В программе выше используются функции: TC_SysLatency, TC_CpuUsage, GETCPUCOUNTER. Также используется информация из встроенного глобального массива SystemTaskInfoArr[]. Он предоставляет структуру данных SYSTEMTASKINFOTYPE.
TC_SysLatency пропустим, я по прежнему не вижу в нем смысла. TC_CpuUsage возвращает целое число процентов нагрузки на процессор. Это значение должно совпадать с графиком в System Manager, но это не точно и это было видно выше.
GETCPUCOUNTER работает независимо от счетчика в CPU. Это счетчик 100 наносекундных циклов. Увеличение на единицу соответствует прошедшему времени в 100 нс. Увеличение на 10 соответствует 1 микросекунде. Посмотрим как перевести в миллисекунды с десятичными долями:
52'108'000 наносекунд = 52'108'0 100*нс = 52'108 микросекунд = 52,108 миллисекунд.
LREAL cpuCntMs := (cpuCntLoDW + cpuCntHiDW) / 10000.0
Счетчик можно использовать для профилирования времени выполнения отдельных блоков программы внутри цикла. Можно узнать сколько времени занимает выполнение подпрограммы или функционального блока.
SystemTaskInfoArr[] в том же цикле отдает структуру SYSTEMTASKINFOTYPE. Индексом для массива служит номер текущей задачи. Индекс можно получить с помощью функции GETCURTASKINDEX в этом же цикле и начать его использовать уже в следующей строке программы.
Структура SYSTEMTASKINFOTYPE содержит состояние предыдущего цикла. Эта структура содержит:
- cycleTimeExceeded — TRUE = время цикла превышено, FALSE = время выполнения в норме. Значение параметра не фиксируется, в каждом цикле оно может быть разным. Всё зависит от времени исполнения предыдущего цикла.
- cycleTime — максимально возможное время на выполнение цикла. Задается в сотнях наносекунд. Для перевода в миллисекунды, разделите значение cycleTime на 10000.0.
- lastExecTime — время выполнения программы в предыдущем цикле. Предыдущего, потому что текущий цикл еще только выполняется, вот прямо сейчас, в данный момент. Значение в сотнях наносекунд.
- cycleCount — номер текущего цикла от момента включения контроллера. Если номер цикла умножить на длительность цикла cycleTime, можно узнать сколько прошло времени с момента включения контроллера.
В TwinCAT 3 массив поменял имя на _TaskInfo[], а структура стала более подробной и теперь называется PlcTaskSystemInfo.