0

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

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

到目前为止我目前的设计:

CLIENT ------> LOG MODULE ---->压缩并存储在内存缓冲区 1 中

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

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

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

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

到目前为止的尝试:为我们将使用的每个字符分配一个代码。似乎没有那么灵活。

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

4

1 回答 1

1

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

一般来说,算法越慢,内存越多,压缩比就越好。不同的编解码器做出不同的权衡,即使在某些编解码器中,您也可以调整不同的参数以产生不同的权衡。

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

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

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

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

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

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

于 2017-02-12T00:44:08.003 回答