ор.Ольга
Решетняк
Обсудить задачу
К схемам A7

База. Язык.
Серверная платформа.

Я написала основную часть исходного сервера A7, а затем самостоятельно переработала его ядро на C++17 без Qt. Здесь — устройство системы, инженерные решения и результаты измерений.

A7 / A7SystemsC++17 · Linux

Что делает A7

A7 начинался с задач сбора, обработки и анализа данных с узлов учёта. Платформа применяется в автоматизации зданий и умного дома: связывает оборудование, серверную логику и клиентские приложения.

Моя область работы — серверная часть. Она принимает сообщения разных протоколов, приводит данные к общей объектной модели, выполняет скрипты, хранит состояние и передаёт изменения подписчикам.

Оборудование и клиентские экраны помогают увидеть границы системы. За любым показанием в интерфейсе стоят объекты, правила доступа, протокольные плагины и доставка изменений.

Админка A7: поля выбранного объекта и панель серверного скрипта
Объектная модель через интерфейс администрирования. Экран показывает данные и состояние сервера; его можно открыть крупнее.

Новая реализация ядра проверяется на стендах и в песочнице; перенос плагинов и работа с продуктовыми конфигурациями продолжаются. История эксплуатации A7 относится к платформе, а решения ниже — к её новому ядру.

Объекты в памяти.
Состояние на диске.

Устройство, помещение или прикладная сущность представлены объектом с полями и связями. Плагины и скрипты работают с общей моделью, а внешние приложения получают доступ к ней через серверные интерфейсы.

Рабочие объекты живут в арене с неподвижным базовым адресом; внутренняя адресация использует смещения. Слой сохранения отвечает за журнал изменений, снимки и восстановление при запуске.

building
 └─ room_12
     └─ sensor_07
         temperature: 22.4
         humidity: 48

Это условный пример модели комнаты. На живой схеме можно проследить путь показаний от датчика до подписчиков.

Старая ссылка остаётся старой

Идентификатор объекта содержит номер слота и поколение. После удаления слот можно использовать снова, но поколение меняется: прежняя ссылка не должна превратиться в ссылку на другой объект. Поколения сохраняются и для свободных слотов, чтобы правило действовало после рестарта.

Поле появляется без переписи всей базы

Если у старого объекта ещё нет нового поля, чтение возвращает значение по умолчанию. Место для поля появляется при первой записи. Развитие схемы не требует немедленно переписать каждый объект.

Свой скриптовый движок

Для нового ядра заново реализован JS-подобный язык с классами, наследованием и декораторами жизненного цикла. Скрипты описывают логику рядом с серверными данными.

  1. Разбор
  2. Связывание имён
  3. Компиляция
  4. Виртуальная машина

Скомпилированный результат кэшируется по хешу исходника и может разделяться между потоками. Доступ к базе вынесен в отдельный интерфейс, поэтому поведение языка можно проверять независимо от хранения.

Исполнение под контролем сервера

У виртуальной машины есть бюджет и кооперативная отмена. Фиберы и автоматическая уступка исполнения позволяют длинным скриптам отдавать управление. Обработка исключений помогает локализовать ошибку, сохраняя дальнейший обход объектов.

Совместимость проверяется на разных уровнях: разбор исходников, компиляция и поведенческое сравнение со старым интерпретатором. В сравнительном прогоне зафиксировано 33 совпавших сценария из 33; это результат конкретного набора проверок.

В двух проверенных операциях новый движок оказался примерно втрое быстрее старого. Ниже — отдельные времена арифметики и чтения поля.

Снимок пишется.
Сервер продолжает работу.

Снимок должен зафиксировать согласованное состояние, пока система продолжает принимать данные. В режиме ForkCow запись выполняет дочерний процесс. Основной процесс обслуживает устройства; изменяемые страницы памяти разделяются по мере записи.

Поэтому у сохранения есть два разных времени: пауза сервера и длительность записи. В одном нагрузочном прогоне они составили 12 мс и 3943 мс соответственно. Проигрывание на схеме показывает эту разницу на общей шкале.

Без второй полной копии базы

Потоковый писатель направляет данные в небольшой буфер, затем на диск. Контрольная сумма обновляется по ходу записи. Это устраняет необходимость собирать весь образ базы во втором большом буфере; память для текущих изменений и Copy-on-Write всё равно нужна.

Отказ диска и отказ памяти — разные ситуации

При отказе записи свежие изменения ещё находятся в памяти. Сервер может продолжать обслуживание оборудования, пока запись восстанавливается. Если процесс остановится до успешного сохранения, накопленные изменения будут потеряны.

Исчерпание рабочей памяти требует другого поведения: сервер запрашивает штатную остановку. Политика отказов определяется тем, где находится единственная свежая копия состояния.

Развитие схемы и переход со старого ядра

Паспорт вместо пересборки истории

Идентификаторы типов, координаты полей и версии релизов записаны в паспорт схемы. Он обновляется вместе с конфигурацией. Сервер не должен заново выводить все координаты из всей истории релизов при каждом запуске.

На копии базы примерно с 580 тысячами объектов это сократило готовность сервера с 2973 до 2173 мс. Полная выгрузка объектов и сохраняемых полей — 3,39 миллиона строк — совпала побайтно между двумя способами запуска.

Миграция с независимой проверкой

Мигратор читает старый формат и создаёт новую базу в отдельном каталоге. Проверка выделена в самостоятельный компонент: она восстанавливает ожидаемые объекты и связи по исходной базе независимо от записи нового формата.

В сценарии проверки новая база сохраняется и открывается заново перед сравнением. Это позволяет находить расхождения до переключения на новую реализацию.

Правки конфигурации без рестарта

В режиме разработки изменения накладываются поверх релиза и записываются журналом. Применение и восстановление при следующем запуске должны одинаково понимать добавления, изменения, удаления и откаты.

Редактор и админка работают с этими серверными контрактами: отправляют изменения, показывают объектную модель, диагностику и журналы.

Что изменилось в цифрах

Каждая пара ниже относится к своему сценарию. Скрипты сравниваются со старым A7 19; паспорт схемы — с прежним способом запуска внутри A7 26.

Две операции — примерно втрое быстрее

Сравнение скриптового движка старого A7 19 и нового ядра A7 26. Время одной итерации сценария; меньше — быстрее. Общая шкала обеих диаграмм — 0–800 нс.

Арифметика в цикле

s = s + i2,8× быстрее
A7 19
396 нс
A7 26
140 нс

Чтение поля из скрипта

o.localport3,1× быстрее
A7 19
765 нс
A7 26
250 нс

29.08.2026 · Intel i9-9900KF · оба сервера в Release · 10⁶ повторов · сопоставимые базы. Чтение поля измерено в точечной форме. Коэффициенты относятся к этим операциям, а не ко всем скриптам или серверу целиком. Как измерялось

Запуск без пересборки всей истории

Паспорт схемы хранит координаты типов и полей. В этом прогоне сервер построил одну схему вместо двадцати девяти.

29 сборок схемы1 сборка схемы

До готовности сервера

−27% времени запуска
По истории
2973 мс
По паспорту
2173 мс

На 800 мс меньше на одной копии базы.

28.08.2026 · около 580 тыс. объектов · 29 релизов · Debug без плагинов. Это оптимизация запуска внутри A7 26. Число сборок 29 → 1 описывает данный прогон, а не ускорение в 29 раз. Условия сравнения

Условия и источники измерений

Числа взяты из сохранённых отчётов проекта. Это исторические результаты конкретных прогонов; новые бенчмарки для этой страницы не запускались.

Скрипты: старый A7 19 и новое ядро A7 26

Отчёт «Скриптовый движок: измеренные числа», 29.08.2026, и базовый журнал A7ScriptBridge. Intel i9-9900KF, оба сервера в Release, цикл на 10⁶ повторов, сопоставимые базы.

396 → 140 нс — арифметика s = s + i. 765 → 250 нс — точечное чтение o.localport. Коэффициенты получены делением старого времени на новое. 133 нс голого имени относятся к другому микробенчмарку и в это сравнение не входят.

Старый сервер в сравнении вызывается по HTTP. Прогоны с разным числом итераций отделяют одноразовую стоимость запуска, компиляции и обвязки от выполнения. На этой машине отдельные дельты могут заметно колебаться, поэтому результат не переносится автоматически на любую нагрузку.

Паспорт схемы: готовность сервера

Отчёт о паспорте схемы, 28.08.2026. Одна копия базы нагрузочного стенда CleverHub: около 580 тыс. объектов, 29 релизов, Debug без плагинов.

2973 → 2173 мс до готовности сервера; 29 → 1 построенная схема. Сокращение времени — 800 мс, или 26,9%, округлённо 27%. Это оптимизация внутри v26. В некоторых конфигурациях паспорту нужны две сборки схемы, поэтому результат 29 → 1 относится именно к этому прогону.

Подключения, память и протокольный отклик

Журнал CleverHub, раздел «Терминатор хабов: базовые числа не поехали». 30 000 виртуальных хабов успешно вошли, последний — через 4,37 с. Приращение RSS сессий составило 20 МиБ; keepalive контрольного хаба — p50 0,130 мс и p99 5,7 мс, 197 измерений.

Хабы не равны квартирам или конечным ZigBee-устройствам. Keepalive не измеряет задержку физического управления, а приращение памяти сессий не равно всей памяти сервера.

Пауза и фоновая запись снимка

Отчёт ForkCow от 07.08.2026: синтетический парк 33 140, поток 5000 входящих кадров/с. Пауза сервера — 12 мс, запись образа дочерним процессом — 3943 мс. На медленном VPS отдельно зафиксирована пауза 263 мс.

Длительности на схеме совмещены для сравнения, а не изображают точную трассу всех фаз. Они зависят от стенда и диска. Движение точек и показания комнаты — иллюстрация архитектуры, не телеметрия.

Расскажите,
что нужно
сделать.

Для первого сообщения достаточно описать, что уже работает и что хочется изменить.

Написать в Telegram@tgtoolga

Можно начать с небольшой задачи. Объём, сроки и результат согласуем до начала этапа.

ИП · договор · счета · NDA
ор.
© 2026 Ольга РешетнякИП Решетняк Ольга Валентиновна

Платформа A7 — продукт
компании A7Systems

Наверх