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



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

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

我目前的设计:

客户端----->日志模块---->压缩并存储在内存缓冲区1 中

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

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

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

如果可能的话,我想要一种不将压缩代码存储在中间数据结构中的算法——也就是说,如果系统崩溃,我希望能够解压缩迄今为止写入文件的任何内容。

迄今为止的尝试:为我们将要使用的每个字符分配一个代码。看起来不那么灵活。

大多数日志消息都是简单的文本语句

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

通常,算法越慢、越需要内存,压缩率就越好。不同的编解码器进行不同的权衡,即使在某些编解码器中,您也可以调整不同的参数以产生不同的权衡。

编解码器对于不同的数据也往往表现得非常不同。有几个基准浮动,但这只会让你对性能有一个大致的了解;要真正选择最好的,你需要用你的数据来尝试,并进行自己的测量。

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

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

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

这里的主要障碍是很多算法不支持刷新。在我的脑海中,gzip、lzham、brotli、bzip2、lzma、zstd和I认为lz4f支持刷新。如果你进行了大量的刷新,bzip2可能不会表现得很好,如果这是一个新系统,那么可能没有太多理由使用gzip或lzma(zstd在各个方面都优于gzip,brotli和lzham在各个方面几乎都优于lzma)。

也就是说,如果你只是想避免你的代码崩溃导致的数据丢失(即,你想在程序崩溃时保留数据,但不太担心操作系统崩溃),你可能需要考虑将压缩和i/O代码拆分到一个单独的进程中。在这一点上,您最终会得到类似于syslog的东西,或较新的结构化日志API,如journed、ASL,或令人惊讶的令人不快的Windows事件日志API。

最新更新