Opened 4 months ago

Closed 4 months ago

#655 closed улучшение (готово)

Оптимизировать учет аварий в "журнале аварий"

Reported by: alx Owned by: alx
Priority: средний Milestone: 1 очередь
Component: swd Keywords:
Cc:

Description

В плате SW-01 организован отдельный "журнал аварий", в который наносятся возникающие аварии, а также фиксируется время из завершения. Журнал организован в виде базы данных sqlite. Иногда при эксплуатации аппаратуры возникают ситуации, когда идет постоянный поток событий - периодическое возникновение и пропадание аварий (например из-за регулярного пропадания и восстановления входного сигнала на портах оборудования). В такой ситуации события могут поступать быстрее, чем они записываются в базу данных. Такая ситуация приводит к повышенной загрузке системы и возможным потерям записываемой в журнал аварий информации.

Был проведен ряд тестов, которые показали, что при возникновении аварий новые записи в БД (INSERT) записываются за константное время, в то время как запросы завершения аварий (UPDATE) выполняются за линейное время, и-з за чего при большом размере БД (100000 записей) производительность падает до единиц запросов в секунду.

Предлагается оптимизировать запись в БД завершений аварий следующим образом:

  • При добавлении новой записи об аварии в БД сохранять ROWID в памяти в специальном хэше. В качестве ключа использовать комбинацию номера слота и oid аварии. Максимальный размер кэша ограничить достаточно большим разумным числом (например 1000), чтобы туда помещалось подавляющее большинство активных аварий в блоке (в идеале - все).
  • При завершении аварии искать соответствующий ROWID в кэше по ключу slot-oid, и если он найден, обновлять запись по условию WHERE ROWID=N. Если ROWID в кэше не найден (из-за переполнения кэша), выполняется fallback на старый вариант запроса WHERE slot=S AND oid='xxxxx' AND end IS NULL.

Как показали эксперименты, запрос записи завершения аварии по ROWID выполняется за константное время. Таким образом, общая производительность записи в БД составляет около 230 запросов в секунду при использовании UBIFS и около 60 запросов в секунду при использовании JFFS2 независимо от размера БД.

Change History (8)

comment:1 by alx, 4 months ago

Summary: Оптимизировать учем аварий в "журнале аварий"Оптимизировать учет аварий в "журнале аварий"

Блин! :)

comment:2 by alx, 4 months ago

С хэшем получается неудобно, так как, во-первых, иногда случается "групповое" завершение аварий (всех аварии платы), и непонятно, как их потом "вычистить" из кэша. Если не вычищать, они будут там копиться, и кэш может переполниться и просто перестать работать. Как вычищать мусор из кэша непонятно - старые записи от новых никак не отличаются, а добавллять ради этого таймстемп и потом по нему сортировать - слишком громоздко и затратно.

Решил вместо хэша использовать просто список элементов, в которых хранить слот, oid и ROWID. При добавлении новых элементов в "голову" списка те аварии, которые часто возникают и завершаются, будут всегда в начале списка, и их поиск будет выполняться быстро. В то же время при переполнении списка можно просто удалять элементы из "хвоста".

comment:3 by alx, 4 months ago

Resolution: fixed
Status: newclosed

In 2337/sw:

Значительно ускорена запись завершения аварий в журнал аварий.

При добавлении новых аварий в БД ROWID запоминается в ОЗУ
вместе с ключом (номером слота и OID аварии) в виде списка.
При завершении аварии выполняется поиск аварии в списке.
Если авария найдена, обновление записи в БД выполняется по ROWID.
Такая операция имеет почти константную сложность вместо линейной в
случае поиска записи по условию (slot, oid, end). За счет этого
в случае полностью заполненной таблицы достигается ускорение
на два порядка. Closes #655.

comment:4 by alx, 4 months ago

Resolution: fixed
Status: closedreopened

Поздно сообразил, что надо было просто добавить правильный индекс.

comment:5 by alx, 4 months ago

Resolution: готово
Status: reopenedclosed

Провел еще ряд экспериментов. Наиболее оптимальные результаты получились при добавлении индекса slotend ON test(slot, end). С таким индексом получается около 150 запросов в секунду на UBIFS и около 35 запросов в секунду на JFFS2.

comment:6 by alx, 4 months ago

Resolution: готово
Status: closedreopened

Тикет был закрыт по ошибке.

Считаю, ранее сделанные изменения следует откатить в пользу решения с добавлением индекса.

comment:7 by alx, 4 months ago

In 2339/sw:

Откатили коммиты r2337-22338. See #655.

comment:8 by alx, 4 months ago

Resolution: готово
Status: reopenedclosed

В r2340:

Значительно ускорена работа журнала аварий.

В журнале аварий убраны все не очень нужные индексы,
и вместо них добавлен один индекс по столбцам slot и end.
Теперь записи о возникновении и завершении аварий в журнал
происходят со скоростью около 180 запросов в секунду
на UBIFS и около 45 запросов в секунду на JFFS2.
Считаю, что такой производительности более чем достаточно.

Note: See TracTickets for help on using tickets.