April 28, 2015

Перформанс ADS.API под .NET

Как утверждает мой проводник, на этом компьютере есть библиотека TwinCAT.Ads.dll, которая позволяет обращаться к данным ПЛК через протокол ADS. Библиотека автоматически устанавливается вместе с Твинкатом (как вторым, так и третьим) и кроме нее, есть еще неплохой набор для множества других языков программирования.



Она удобная, есть документация и примеры. Вопрос в том - насколько она быстра?

Вопрос номер два - при наличии большого ассортимента контроллеров и гигантского количества "персоналок", как определить быстродействие и от чего отталкиваться?


Методика


На помощь спешит детерминированность ПЛК-цикла. Время цикла системы реального времени жестко выдерживается, значит мы можем посчитать сколько ПЛК-циклов библиотека ADS.API будет пропускать (или не будет) при использовании быстрого контроллера и быстрого ПК.

Берем ПКЛ Beckhoff CX2020 (подходит для ЧПУ систем) и ноутбук на базе Core i7-3630QM (позиционировался как игровой). Этого достаточно, чтобы "разогнаться" до 50 микросекунд, а меньше и не бывает.

Простейшая ПЛК-программа с заданным временем цикла, содержащая примитивный счетчик +1 каждый цикл. Будем раз-за-разом считывать его значение и замерять разницу между предыдущим и текущим значениями. При разнице в 1, мы получим время считывания равное одному ПЛК-циклу (его значение известно); при разнице в 2, мы получим время считывание равное двум ПЛК-циклам; при 10, соответственно 10 циклов на считывание одной переменной и т. д. Длина переменной счетчика типа UDINT = 4 байта. Чуть позже попробуем считывать строку длиной 100 байт и массив подлиннее.



Быстродействие


Синхронное чтение с помощью ReadAny() одной переменной длинной UDINT занимает 5..10мс. При асинхронном чтении с помощью уведомлений [event driven] и функции AddDeviceNotification(), можно разогнаться до 1мс: меньше не получится - это ограничение функционала библиотеки. Следует учесть, что такое поведение справедливо для обмена данными в UI-потоке: там же, где происходит обработка интерфейса пользователя (интерфейса как графического, так и консольного).

Синхронный обмен можно разогнать, если запустить поллинг (постоянный опрос) в параллельном потоке и считывать из него данные по мере необходимости. В таком случае можно "разогнаться" до 50мкс и даже намного быстрее, что конечно же бессмысленно т. к. ПЛК не сможет выдать данные быстрее своего цикла.


Объем


Оценка скорострельности бессмысленна без объема перекачиваемых данных. В тестах выше использовалась единственная переменная типа UDINT размером 4 байта. Что произойдет, если взять данных да побольше?

Количество последовательных синхронных операций ведут себя линейно - чем больше запросов, тем больше времени понадобится: два запроса удвоят время, три - утроят и т. д. Что если в одном запросе передать больше данных? Выше мы хотели посмотреть на строки и массивы, но т. к. это одно и то же (строки - это массивы символов с нулем в конце), то тестировать будем массивы разной длины.
Уточнение для педантичных разработчиков: я проверил работу со строками разной длины - оно работает аналогично линейным одномерным массивам байт. Никаких подводных камней.
И тут внезапно ждет печаль и разочарование - получить какие-то точные данные не получается: время запросов начинает сильно плавать как в синхронных, так и в асинхронных запросах. Вполне нормальное явление, когда детерминированное встречается с недетерминированным, но хотелось бы рекомендаций:
  1. Асинхронное однопоточное чтение быстрее синхронного однопоточного.
  2. Многопоточное синхронное чтение быстрее однопоточного асинхронного. "Сверхбыстродействие" можно получить созданием отдельного потока для поллинга синхронными функциями.
  3. Массив можно прочитать/записать за один вызов функции и за такое же время, как для одной простой переменной.
  4. Как следствие, для передачи большого количества переменных, их желательно упаковать в массив. Упаковать - не значит сжать, просто разместить.
  5. Начиная с размера массива в 16 килобайт, время запроса увеличивается нелинейно - становится чуть длиннее. Это связано с пакетной отправкой запросов и прочей сетевой кухней.
  6. После 16 килобайт, чем длиннее массив, тем больше времени понадобится на чтение/запись. До 16 килобайт объем данных на время обмена не влияет.
  7. 16 килобайт получено эмпирически для CX2020 и размера сетевого пакета "по умолчанию".

Представленная методика конечно же кривая, косая и неточная, но позволяет хоть как-то оценить и представить быстродействие обмена данными через ADS.API. К тому же, позволяет выбрать тип обмена: синхнронный, многопоточный, событийный асинхронный и т. п.

No comments

Post a Comment

Note: Only a member of this blog may post a comment.