Лог-модуль с предварительно выделенной памятью
Я пишу механизм ведения журнала, который будет использоваться оставшейся частью кода для записи буквенно-цифровых данных в файл. Любой другой модуль в системе будет посылать буквенно-цифровые предложения (максимум пара слов) для записи в файл непрерывно. Суть в том, что мне дали только небольшое количество предварительно выделенной памяти, чтобы использовать ее для структур данных и хранения этих сообщений журнала в памяти. Если приток больше того, что может быть записано на диск, сообщения журнала будут отброшены.
Я хочу вставить механизм сжатия между клиентом и хранилищем в памяти в моем модуле журнала, чтобы я мог сохранить как можно больше сообщений.
Мой текущий дизайн до сих пор:
КЛИЕНТ ------> LOG МОДУЛЬ ----> сжать и сохранить в буфере в памяти 1
Поток записывающего устройства: когда пришло время писать, переключите буфер 1 с буфером 2 и запишите буфер 1 в файл. Клиент будет записывать в буфер 2 в течение этого времени.
Сценарий снаружи:распаковать и показать сообщения журнала
Вопрос: Что такое хороший алфавитно-цифровой алгоритм сжатия, который я могу использовать, или хорошую структуру данных, которую я могу использовать, чтобы захватить как можно больше данных (на стадии сжатия выше)?
Если возможно, я бы хотел алгоритм, который не хранит код сжатия в промежуточной структуре данных - то есть, если система выходит из строя, я хочу иметь возможность распаковывать все, что было записано в файл до сих пор.
Попытка до сих пор: назначьте код для каждого персонажа, который мы будем использовать. Не кажется таким гибким.
Большинство сообщений журнала представляют собой простые текстовые предложения
1 ответ
Вопрос: Что такое хороший алфавитно-цифровой алгоритм сжатия, который я могу использовать, или хорошую структуру данных, которую я могу использовать, чтобы захватить как можно больше данных (на стадии сжатия выше)?
В общем, чем медленнее и более требователен алгоритм, тем лучше степень сжатия. Разные кодеки дают разные компромиссы, и даже в некоторых кодеках вы можете настроить разные параметры для получения разных компромиссов.
Кодеки также имеют тенденцию работать очень по-разному с различными данными. Есть несколько тестов, но это только даст вам общее представление о производительности; чтобы действительно выбрать лучший, вам нужно опробовать их на своих данных и провести собственные измерения.
Что касается предотвращения потери данных в случае сбоя вашего процесса, то в соответствии с текущим дизайном вам необходим потоковый кодек, который поддерживает сброс. Каждый раз, когда вы заканчиваете регистрировать сообщение, вы хотите сказать, чтобы кодек сбросился. API для этого будет зависеть от кодека, но обычно вы получите что-то вроде
foo_compress(stream, output, input);
foo_flush(stream);
fwrite(stream->output, 1, stream->output_size, file);
fflush(stream);
Несколько библиотек предоставляют API для чтения / записи на диск (позволяя пропустить fwrite
/ fflush
). Вспоминаются сквош, гзип и лжам, но, вероятно, есть и другие. По большей части, однако, библиотека просто сжимается в буфер, и вы отвечаете за запись буфера в файл.
Ваше главное препятствие в том, что многие алгоритмы не поддерживают сброс. Сверху моей головы, gzip, lzham, brotli, bzip2, lzma, zstd, и я думаю, что lz4f поддерживает сброс. bzip2, вероятно, не будет работать очень хорошо, если вы выполняете много операций очистки, и если это новая система, вероятно, нет особых оснований использовать gzip или lzma (zstd превосходит gzip, а brotli и lzham превосходят lzma почти во всех путь).
Тем не менее, если вы просто пытаетесь избежать потери данных из-за сбоев в коде (т. Е. Хотите сохранить данные при сбое вашей программы, но не слишком беспокоитесь о сбое ОС), вы можете рассмотреть возможность разделения. сжатие и ввод-вывод кода в отдельный процесс. На этом этапе вы получите что-то похожее на syslog или более новые API структурированных журналов, такие как journald, ASL или удивительно неприятный API-интерфейс Windows Event Log.