二值化数据的最佳方法是什么

时间:2011-03-16 14:27:48

标签: c++ data-serialization

我有一些写为tag = value的数据文件,其中tag是字符串,value可能是数字,字符串,数组等。我使用这种格式,因为它是可读的,可以轻松编辑。现在,使用此格式实例化的每个类都有一个加载方法,它会读取所需的标记并使用这些标记中的值。我想制作二进制数据以提高加载速度。一种方法是在每个读取旧数据并将其写入文件的类中使用ToBinary(名称无关紧要)方法,新文件用于实例化对象。这可以离线完成,只需一次/应用。你有其他建议吗?我使用C ++。

编辑: 我认为现在最昂贵的部分是在我第一次阅读时解析文件,之后搜索我需要的标签,而不是从磁盘读取文件。我可以使用自定义文件系统在一个大文件中包含多个小文件。

6 个答案:

答案 0 :(得分:1)

我之前没有使用它,但我确信Boost's Serialization module是一个很好的起点。

答案 1 :(得分:1)

如果您使用的是文件,那么使用二进制数据可能无法显着改善您的表现,除非您有大量数据存储在文件中(图像,视频......)。

但无论如何,您可以使用二进制序列化算法,例如来自Boost的算法。

答案 2 :(得分:1)

我有一个序列化基类,To / From函数带有一个小标题,可以嵌入版本处理。我认为它是一个很好的系统,需要在本地存储更简单的数据,在大多数情况下是“只读”。

这样的事情:

class SeralizeMe
{
public:

 virtual bool To(Archive &file)=0;
 virtual bool From(Archive &file)=0;

 virtual bool NeedsSave(void)=0;

};

但是,如果您:

,请不要使用此系统
  • 需要经常更改格式。
  • 需要选择要加载的数据和要存储的内容。
  • 使用大型文件,这些文件在保存时特别容易停电。

如果上述任何一种情况适用,请使用数据库,FirebirdSQL embedded是一个合适的竞争者。

答案 3 :(得分:0)

另一个是谷歌的protobuf。不是最快的,但它可以支持不断发展的数据类型,并且在网络上非常高效并支持其他语言。

链接here

答案 4 :(得分:0)

如果要提高性能,则必须使用固定长度字段。解析或加载可变长度字段不会显着提高性能。通过文本行读取涉及扫描行结束标记。扫描浪费时间。

在使用以下任何建议之前,请对代码进行概要分析,以确定性能的基准时间或数字。在每个建议之后执行此操作,因为它将使您能够计算每个优化的性能增量。我的预测是每次优化后delta会变小。

我建议首先将文件转换为固定长度的记录,仍然使用文本。根据需要填充带空格的字段。因此,知道记录的大小,您可以阻止读入内存并将内存视为数组。这应该提供显着的改进。

此时,您的瓶颈仍然是文件I / O速度,您无法真正对其进行重大改进(因为文件I / O由操作系统控制),以及扫描/转换文本。一些进一步的优化是:将文本转换为数字,最后转换为二进制。 不惜一切代价,更愿意将数据文件保持为人类可读的形式。

在使数据文件的可读性降低之前,请尝试将应用程序拆分为线程。一个线程处理GUI,另一个线程处理输入,另一个线程处理。想法是让处理器始终执行一些代码而不是等待。在现代平台中,可以在CPU处理代码时执行文件I / O.

如果您不关心可移植性,请查看您的平台是否具有DMA功能(DMA或直接内存访问组件允许在不使用处理器的情况下进行数据传输或最大限度地减少处理器的使用)。值得注意的是,许多平台共享处理器和DMA之间的地址和数据总线。因此,一个组件被阻塞或暂停,而另一个组件使用地址和数据总线。所以它可能有所帮助。取决于平台的连接方式。

转换关键字段以使用数字,a.k.a。标记。由于标记是数字的,因此它们可以用作跳转表(也是switch语句)的索引,或者只是索引到数组中。

作为最后的手段,将文件转换为二进制文件。二进制版本应该有两个字段:key作为标记和值。将大块数据传输到内存中。

摘要

  1. 将大块数据传入 存储器中。
  2. 更改前的配置文件 建立基准绩效 测量
  3. 一次优化一步, 每次优化后进行分析。
  4. 喜欢将数据文件保存在人体中 可读形式。
  5. 尽量减少对数据文件的更改。
  6. 将文件转换为使用固定长度 字段。
  7. 尝试使用线程或多任务处理 所以应用程序没有等待。
  8. 将文本转换为数字标记 (降低人的可读性)
  9. 将数据转换为二进制 度假村(对人类来说非常困难 读&调试)。

答案 5 :(得分:0)

我有两个想法:

1)如果标签列表是常量并且事先已知,您可以将每个标签转换为BYTE(或WORD),然后是值的长度(以字节为单位),然后是原始c字符串价值的有效载荷。

例如,给出以下内容:

Tag1 = "hello World!" // 12 bytes in length (achieved by "strlen(value) * sizeof(char)" )
Tag2 = "hello canada!"  // 13 bytes in length 

您可以将其转换为字节流:

0x0001 0x000B // followed by 12 bytes representing the 'value' // 0x0002 0x000C // followed by 13 bytes representing 'value2'

您的程序只需要知道WORD标题“0x0001”代表Tag1,标题“0x0002”代表Tag2。

如果你事先不知道它们,你甚至可以通过遵循类似的长度,价值结构来进一步抽象标签名称。

2)也许慢点只是你文本解析的实现?考虑使用专用的开源库来实现您的目标。示例:“boost::property_tree

属性树专门用于存储和检索键值对(设计用作配置设置文件)。但我想这将取决于你为此存储多少个这样的对来是经济的。