dollar
@dollar
Делай добро и бросай его в воду.

Как сохранять состояние приложения, чтобы не было лага?

Приложение работает в реальном времени. У него есть очень сложное и большое состояние в виде древовидной структуры, которая постоянно меняется. Причем, меняются не только значения полей, но и сама структура: например, в массивах могут появиться или исчезнуть элементы или может измениться их сортировка. Графы и хеш-таблицы тоже подвержены всевозможным изменениям.

Попытка сериализовать всю эту структуру целиком (во что-то типа JSON или BSON) занимает несколько секунд.

Как сохранить состояние, не прерывая работу приложения?
  • Вопрос задан
  • 363 просмотра
Решения вопроса 2
sgjurano
@sgjurano
Разработчик
Используйте fork, дочерний процесс за счёт механизма Copy-on-Write в наследство практически бесплатно получает копию памяти родителя (это если у вас Linux).

Такой подход позволяет сделать fork, после этого в родительском процессе заниматься дальнейшей работой, а в дочернем не торопять дампить что нужно на диск.

Мы таким образом дампим индекс размером в десятки гигабайт практически без влияния на производительность и почти без роста затрат памяти, ровно так же это делает например redis (rdb).
Ответ написан
Что значит в реальном времени, у вас ОС реального времени?

1)Может вам не состояние сохранять а вести журнал всех изменений, и по требованию восстанавливать структуру воспроизводя действия из журнала в том же порядке. Как БД делают с транзакциями, журнал транзакций, сначала пишем в него, а потом уже пытаемся выполнить. Только не удалять потом из него, что то вроде Event Sourcing получается. Таким подходом у вас в любой момент можно восстановится до последнего состояния до сбоя/выключения. но лог огромным может быть, их помоему можно склеивать.

Идея такая - посмотреть как работают Inmemory DB, SQL, NoSQL.

2)Идеально было бы не заморачиваться так.
Возможно сдлеать что то типо команд.
В ПО летит команда - сделай что то с объектом.
Вы эту команду кидаете менеджеру.
Менеджер хранит две копии одинаковых объектов, и для каждого из них держит две одинаковые очереди команд. Когда объект готов, он берет команду из своей очереди, и выполняет ее.
Вы нажимаете сохранить копию объекта на диск.
Менеджер берет говорит одному из объектов - сохранись на диск, тот перестает выполнять поступающие команды, и сохраняется на диск. После этого продолжает выполнять команды, догоняя своего соседа. Догонит он его или нет не понятно, но вот что он будет его копией на момент времени Х, определенно.
Памяти будет кушать много (два объекта, две очереди, одна из которых может "опаздывать/догонять"), но в теории должно работать.
Это напоминает асинхронную реплику, только в памяти и там том же устройстве.

2.1) В памяти может быть только один объект. Менеджер при поступлении служебной команды на сохранения объекта, может продолжать складировать обычные команды в очередь дальше, как объект сохраниться, он продолжит брать команды из нее.
Приложение не будет зависать, но и мгновенное выполнение команд не гарантируется.

3) Сделать клон в памяти быстрее чем на диске. Делаем клон в памяти, и сохраняем его на диск, после удаляем (мержить и догонять не нужно, проще удалить целиком и сделать новый когда потребуется).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
При сохранении - клонируйте существующую структуру (в оперативке; или всегда держите клона "живым", если памяти хватит) и уже её - сохраняйте асинхронно в доп. потоке.

Если "клон" - то ставим его обновление на паузу: "отцепляем" от основной структуры связь.
После сохранения на диск - сбрасываем состояние клона в "болванку"/reset и восстанавливаем связь, чтобы "клон" "ожил".
Ответ написан
profesor08
@profesor08
Создай новый поток и в нем делай все свои дела. Он будет жить своей жизнью, все остальное приложение своей. Это же очевидно, раз подвисает, значит операции синхронные и надо распараллелить.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы