Предложена методика измерения скорости заполнения буфера при вводе данных и передаче их по сети, основанная на применении сетевых инструментов разработчика в современных браузерах.
Ключевые слова: микроконтроллер, Ethernet, HTTP, скорость передачи данных, скорость заполнения буфера.
Необходимость в некоторых ситуациях исследовать параметры производительности компьютерных систем никуда не пропадает несмотря на всё развитие технологий [1]. Задачей представляемой работы было определение того, что и насколько ограничивает возможности ввода данных в сеть через параллельный порт микроконтроллера:
— собственно конкретный микроконтроллер ATmega2560 и тот его программный код, который занимается вводом данных и их временным накоплением во внутренней оперативной памяти (в буфере);
— сетевой контроллер W5500 с его интерфейсом SPI и тот программный код в ATmega2560, который занимается передачей данных из буфера по 100-мегабитной сети с обычным стеком TCP/IP и HTTP.
Решение второй части задачи было экспериментально получено в [2]. Эксперименты показали, что указанные аппаратные средства позволяют достичь скорости передачи информации не более примерно 2,5 Мбит/с, причем существовавшие тогда версии библиотеки Ethernet [3] для W5500 могли при неудачном выборе размера буфера намного ухудшить скорость.
Рассмотрим далее следующее решение первой части задачи.
- Создаем в ATmega2560 тестовый HTTP-сервер. В ответ на запрос GET программа должна будет посылать содержимое буфера известного объема, выделенного в оперативной памяти микроконтроллера:
union int_char {
int i [1024]; // по отсчетам
char ch [2048]; // по байтам
};
int_char transmittedData;
Тип int_char позволяет упростить работу с одним и тем же буфером как с массивом байтов, так и с массивом 16-битовых целых чисел.
- Создаем в программе цикл заполнения буфера. Например, в таких вариантах:
— заполнение возрастающими 16-битовыми целыми числами:
for (int m = 0; m < 1024; m++) {transmittedData.i [m] = m;}
— заполнение возрастающими байтами:
for (int m = 0; m < 2048; m++) {transmittedData.ch [m] = m;}
— ввод байтов с параллельного порта:
for (int m = 0; m < 2048; m++) {transmittedData.ch [m] = PINA;}
- Создаем внешние циклы и вызов функции передачи буфера в сеть client.write:
for (int k = 0; k < 1000; k++) {
for (int n = 0; n < nmax; n++) { // вводим данные
for (int m = 0; m < 2048; m++) {transmittedData.ch [m] = PINA;}
}
client.write(transmittedData.ch, 2048); // посылаем данные
}
Чтобы повысить точность измерений программа повторяет заполнение и передачу буфера много (1000) раз подряд. Дополнительно можно увеличивать долю операций заполнения, задавая количество внешних циклов заполнения буфера nmax.
- Запустив HTTP-сервер, с помощью инструментов разработчика в браузере (рис. 1) измеряем суммарное время многократного заполнения и передачи буфера. Это параметр Content Download (время передачи контента).
Рис. 1. Длительности состояний одного запроса GET
- Повторяем измерения для разных nmax от 0 до 10 и строим диаграмму (рис. 2). Нелинейный вид зависимости в начале графика объясняется тем, что функция client.write библиотеки Ethernet возвращает управление основной программе не дожидаясь конца текущей передачи модуля W5500 по сети, а несколько раньше, когда она передала весь буфер в память модуля. За это время успевает отработать примерно один проход внешнего цикла заполнения буфера.
- Зная время передачи контента 6,28 c при nmax = 0, и общий объем посланных данных 2048*1000 байт = 2048000 байт = 2048000*8 бит = 16384000 бит, вычисляем скорость передачи данных по сети (16384000 бит)/(6,28 c) = 2,61 Мбит/с. Это значение, ограниченное возможностями модуля W5500 и его программного обеспечения.
- Выбираем две точки, расположенные далеко друг от друга, но находящиеся на прямолинейно возрастающем участке диаграммы. Например, здесь это точки с nmax = 2 и nmax = 10.
Рис. 2. Время передачи контента в зависимости от количества внешних циклов заполнения буфера nmax
Вычисляем прирост nmax как разность 10–2 = 8. Вычисляем соответствующий прирост времени: 12,63 с — 6,96 с = 5,67 с. Вычисляем время одного внешнего цикла заполнения буфера как отношение приростов: (5,67 с)/8 = 0,709 с.
- Зная время 0,709 c и общий объем заполняемых данных 2048*1000 байт = 2048000 байт = 2048000*8 бит = 16384000 бит, вычисляем скорость заполнения буфера (16384000 бит)/(0,709 c) = 23,1 Мбит/с. Это значение, ограниченное возможностями ATmega2560 и программного обеспечения заполнения буфера.
- Зная время 0,709 c и общее количество проходов цикла 1024*1000 = 1024000, вычисляем время одного прохода (0,709 c)/1024000 = 692 нс.
- Зная время одного прохода 692 нс и тактовую частоту 16 МГц, вычисляем количество тактов на один проход цикла (692 нс)*(16 МГц) = (692 нс)*(0,016 ГГц) = 692*0,016 = 11.
Аналогично были получены параметры для других вариантов заполнения буфера (табл. 1).
Таблица 1
Измеренные параметры производительности микроконтроллера
Цикл заполнения буфера |
Возрастающими 16-битовыми целыми числами |
Возрастающими байтами |
Ввод байтов с параллельного порта |
Скорость заполнения буфера, Мбит/с |
23,1 |
14,1 |
18,1 |
Скорость заполнения буфера, Мбайт/с |
2,89 |
1,76 |
2,26 |
Время одного прохода цикла, нс |
692 |
566 |
441 |
Количество тактов на один проход цикла |
11 |
9 |
7 |
Количество тактов на один байт данных |
5,5 |
9 |
7 |
Литература:
- Реальная скорость Wi-Fi (на предприятиях) [Электронный ресурс] // Habr. — URL: https://habr.com/ru/articles/431404/ (дата обращения: 02.11.2023).
- Воловач В. И., Будилов В. Н., Есин А. А. Исследование скорости передачи по HTTP при использовании микроконтроллеров ATmega2560 и W5500 // Эволюционные процессы информационных технологий: сборник трудов по материалам 5-й всероссийской научно-технической конференции. — М.: Издательство «Научный консультант», 2020. — С. 101–105.
- Ethernet — Arduino Reference [Электронный ресурс] // Arduino. — URL: https://www.arduino.cc/reference/en/libraries/ethernet/ (дата обращения 02.11.2023).