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

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

有帮助吗?

解决方案

我有一个序列化基类,其中有一个小标头的功能,可以嵌入版本处理。我认为这是一个很好的系统,可以在本地存储,在大多数情况下是“仅读取”。

这样的事情:

class SeralizeMe
{
public:

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

 virtual bool NeedsSave(void)=0;

};

但是,如果您以下内容,请勿使用此系统:

  • 需要经常更改格式。
  • 需要选择要加载的数据以及存储的数据。
  • 使用大型文件,该文件特别适合保存时对停电敏感。

如果有上述任何一种,请使用数据库,嵌入Firebirdsql是合适的竞争者。

其他提示

我以前从未使用过,但我确定 Boost的序列化模块 是一个很好的起点。

如果您使用的是文件,则使用二进制数据可能不会显着改善您的性能,除非您有很大的数据要存储在文件中(图像,视频...)。

但是无论如何,您可以使用二进制序列化算法,例如 促进.

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

关联 这里.

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

在使用以下任何建议之前,请介绍您的代码以建立基准时间或数字以进行性能。在每个建议之后执行此操作,因为这将使您能够计算 性能三角洲 每个优化。我的预测是,每次优化,三角洲都会变小。

我建议首先将文件转换为固定长度记录,但仍使用文本。必要时带有空间的垫子字段。因此,知道记录的大小,您可以将读取为内存并将内存视为数组。这应该提供重大改进。

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

在使数据文件变得较低的读取之前,请尝试将应用程序分配到线程中。一个线程处理GUI,另一个线程为处理,另一个线程用于处理。这个想法是有处理器 总是 执行一些代码而不是等待。在现代平台中,可以在CPU处理您的代码时执行文件I/O。

如果您不关心可移植性,请查看您的平台是否具有DMA功能(DMA或Direct Memory访问组件允许无需使用处理器或最小化处理器的使用)。要注意的是,许多平台在处理器和DMA之间共享地址和数据总线。因此,一个组件被阻止或悬挂,而另一个组件使用地址和数据总线。因此,它可能会有所帮助。取决于平台如何连接。

将密钥字段转换为使用数字,也就是 令牌. 。由于令牌是数字,因此可以将它们用作跳转表(也可以切换语句)或将索引作为数组中的索引。

作为最后的手段,将文件转换为二进制。二进制版本应具有两个字段:键为令牌和值。将大块的数据中的数据运送到内存中。

概括

  1. 将大量数据拖放到内存中。
  2. 进行更改之前的轮廓以建立基线绩效测量。
  3. 一次优化一个步骤,每次优化后进行分析。
  4. 更喜欢将数据文件保留为人类可读形式。
  5. 最小化数据文件的更改。
  6. 将文件转换为使用固定长度字段。
  7. 尝试使用线程或多任务处理,以使应用程序不在等待。
  8. 将文本转换为数字令牌(降低人类的可读性)
  9. 将数据转换为二进制,作为最后的手段(人类很难阅读和调试)。

我有两个想法:

1)如果标签列表是恒定的,并且提前已知,则可以将每个标签转换为字节(或单词),然后将值转换为值的长度(以字节为单位),然后是值的原始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'

您的程序只需要知道标题“ 0x0001”一词代表tag1,而标题“ 0x0002”代表tag2。

如果您不预先知道标签名称,则可以通过遵循类似的长度,价值结构来进一步抽象标签名称。

2)也许慢一点只是您对文本解析的实现?考虑使用专用的开源库来尝试做什么。例子: ”boost :: property_tree"

属性树专门设计用于存储和检索钥匙值对(设计用于配置设置文件)。但是我想这将取决于您试图存储多少这种对经济的对。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top