1.1.0 - печатает дробные числа своим кодом вместо dtostrf
Pre-release1.1.0 — 2 сентября 2026
Предварительный выпуск: библиотека выложена для оценки сообществом, замечания
приветствуются.
Устанавливается из репозитория — в каталоге Arduino и реестре PlatformIO её
пока нет; как это сделать, сказано в README.
Главное в этом выпуске
Дробные печатаются собственным кодом, целочисленной арифметикой, без
dtostrf. Замеры:
| было | стало | ||
|---|---|---|---|
| скорость (300 000 вызовов) | 127.8 мс | 12.3 мс | в 10 раз быстрее |
| флеш, AVR | 3432 | 2052 | −1380 байт |
| флеш, ESP8266 | 266747 | 266535 | −212 байт |
| флеш, ESP32 | 267961 | 268241 | +280 байт |
Против snprintf дробные теперь быстрее в 6.2 раза — раньше отставали в 1.25.
На ESP32 прошивка немного выросла: ветка для чисел от 2³², где дробной части у
double уже нет, печатает целую часть через uint64, а 64-битное деление там
отдельная подпрограмма.
Округление совпадает с printf и dtostrf до последнего знака, включая
правило «ровная половина — к чётному»: сверено на 316 004 значениях.
Исправлено: у -0.0 терялся знак — сравнение с нулём для отрицательного
нуля ложно.
Возможности библиотеки
Полный перечень, включая то, что было в 1.0.0.
Форматирование по образцу. Одно место вставки {} для любого типа вместо
%d, %lu и %.3f. Тип выводит компилятор, поэтому несовпадение типа или
забытый аргумент перестают быть порчей стека.
Готовые правила вывода — числа, строки в RAM и во флеше, String,
длительности, дата и время, IP-адрес, дампы памяти. Свой тип подключается одной
специализацией formatter<T>.
Необязательное значение opt(условие, префикс, значение) — условие пишется
один раз вместо двух тернарных выражений с пустыми литералами.
Журнал с уровнями, источниками и сменными приёмниками вывода. Библиотека
никуда не пишет сама: порт, сеть, карта памяти — решает приложение.
Уровни задаются раздельно по источникам, так что разговорчивую часть
приложения можно приглушить, не трогая остальные. Проверка идёт до сборки
сообщения, поэтому отброшенный вызов почти ничего не стоит.
Порог FMTLOG_COMPILE_LEVEL убирает вызовы из прошивки целиком — вместе с
образцами и значениями.
Необязательные модули. Цветной вывод (FmtColor.h) и чтение строк из
EEPROM (FmtEeprom.h) подключаются отдельно и не занимают места, пока не нужны.
Сколько это стоит
Все числа получены сборкой, не оценкой. Сравнение с snprintf на сообщениях
вида "msg a={} b={}" с двумя целыми.
Флеш
| постоянная надбавка | каждый вызов | |
|---|---|---|
| AVR (Uno) | 676 Б против 1574 Б у snprintf |
108 Б против 97 Б |
| ESP8266 | 512 Б против 336 Б | 77 Б против 59 Б |
На AVR библиотека экономит флеш примерно до 86 вызовов — дальше немного
дороже. На ESP8266 экономии по флешу нет: printf там слинкован ядром
независимо от кода приложения, и FmtLog добавляется поверх. Разница — около
0.1 % флеша на полсотни вызовов.
Дробные выводятся собственным кодом, без dtostrf: на AVR это экономит
1380 байт флеша.
Цветной вывод стоит 456 байт и только когда подключён.
Оперативная память
Динамическая память не используется вовсе. Статически — буфер сообщения
(128 байт, на AVR 64) и состояние буфера: 16 байт на ESP, 7 на AVR. Размер
буфера задаётся при сборке через FMTLOG_MESSAGE_SIZE.
Скорость
против snprintf |
|
|---|---|
| целые | в 2.2 раза быстрее |
| дробные | в 6.2 раза быстрее |
Библиотека печатает и те, и другие сама, целочисленной арифметикой, без
разбора образца во время выполнения.
Округление совпадает с printf и dtostrf до последнего знака, включая
правило «ровная половина — к чётному»: сверено на 316 004 значениях.
Платформы
| платформа | состояние |
|---|---|
| ESP8266 | проверено сборкой |
| ESP32 | проверено сборкой |
| AVR (Uno, Nano, Mega) | проверено сборкой |
На AVR нет IPAddress — соответствующее правило вывода там не собирается.
<type_traits> ядро AVR не поставляет, нужные признаки типов библиотека
определяет сама.
Что проверено
- 60 тестов на машине разработчика, плата не нужна:
pio test -e native - 14 сочетаний примеров и плат собираются; предупреждений от библиотеки нет
- замеры размера и скорости — сборкой, а не оценкой
- вывод дробных сверен с
printfна 316 004 значениях
Известные ограничения
- Спецификаторов ширины и точности у
{}нет: число знаков после запятой
задаётся при сборке черезFMTLOG_FLOAT_DECIMALS, общий для всех значений. - Буфер сообщения один на приложение, поэтому журнал не переживёт вызова из
прерывания во время сборки другого сообщения. - Дата и время принимают время эпохи Unix и печатаются как есть: часовой пояс
библиотека не знает, сдвиг задаёт приложение.