具有预分配内存的日志模块

log module with pre-allocated memory

我正在编写一个日志记录机制,其余代码将使用该机制将字母数字数据记录到文件中。系统中的每个其他模块都将发送字母数字句子(最多几个单词)以连续写入文件。问题是,我只获得了少量预分配内存用于我的数据结构和这些日志消息的内存存储。如果流入量大于可写入磁盘的量,则日志消息将被丢弃。

我想在我的日志模块中的客户端和内存存储之间加入一个压缩机制,这样我就可以保存尽可能多的消息。

我目前的设计:

CLIENT ------> LOG MODULE ----> compress 并存储在内存缓冲区 1

作者线程: 当需要写入时,将缓冲区 1 与缓冲区 2 切换并将缓冲区 1 写入文件。客户端将在此期间写入缓冲区 2。

外部脚本解压缩并显示日志消息

问题: 什么是我可以使用的好的字母数字压缩算法或我可以用来捕获尽可能多的数据(在上面的压缩阶段)的好的数据结构?

如果可能,我想要一种不将压缩代码存储在中间数据结构中的算法 - 即,如果系统崩溃,我希望能够解压缩到目前为止已写入文件的所有内容。

到目前为止的尝试: 为我们将使用的每个字符分配一个代码。好像不太灵活

大部分日志信息都是简单的文字句子

Question: What is a good alphanumeric compression algorithm I can use or a good data structure I can use to capture as much data as possible (during the compression stage above)?

一般来说,算法越慢,memory-hungry 压缩率就越高。不同的编解码器产生不同的 trade-offs,甚至在某些编解码器中,您可以调整不同的参数以产生不同的 trade-offs.

编解码器对不同数据的表现也往往大不相同。周围有几个基准测试,但这只会让您对性能有一个大概的了解;要真正选择最好的一个,您需要 使用您的数据 并进行自己的测量。

至于在进程崩溃时避免数据丢失,根据您当前的设计,您需要的是支持刷新的流式编解码器。每次完成消息记录时,您都需要告诉编解码器进行刷新。 API 取决于编解码器,但通常你会得到类似

的结果
foo_compress(stream, output, input);
foo_flush(stream);
fwrite(stream->output, 1, stream->output_size, file);
fflush(stream);

一些库为 reading/writing 提供 API 到磁盘(允许您跳过 fwrite/fflush)。想到 Squash、gzip 和 lzham,但可能还有其他的。不过,在大多数情况下,库只是压缩到一个缓冲区,您负责将缓冲区写入文件。

这里的主要障碍是许多算法不支持刷新。在我脑海中,gzip、lzham、brotli、bzip2、lzma、zstd 和我 think lz4f 都支持刷新。如果您进行大量刷新,bzip2 的性能可能不会很好,如果这是一个新系统,则可能没有太多理由使用 gzip 或 lzma(zstd 优于 gzip,而 brotli 和 lzham 几乎在每个方面都优于 lzma方式)。

就是说,如果您只是想避免因 您的 代码崩溃而导致的数据丢失(即,您想在程序崩溃时保留数据,但您不太担心 OS 崩溃),您可能需要考虑将压缩和 I/O 代码拆分到一个单独的进程中。到那时,您最终会得到类似于 syslog 或更新的结构化日志记录 APIs 的东西,例如 journald, ASL, or the astonishingly unpleasant Windows Event Log API.