【问题标题】:Why does the amateur implementation of a Fortran version of Delphi's TStringList behaves 10 times lower than Delphi's built-in one?为什么 Fortran 版本的 Delphi 的 TStringList 的业余实现比 Delphi 的内置版本低 10 倍?
【发布时间】:2012-07-07 07:15:34
【问题描述】:

要了解最新的Fortran 的OO 功能,DelphiTStringListFortran 版本在下面编写并链接(gist.github)。 Fortran 源模仿 Delphi 之一。

这个Fortran TStringList 按预期运行。然而,我的问题是,它读取/写入 30MB 文件的 LoadFromFile/SaveToFile 组合比 Delphi 的对应项慢 10 倍。文件越大,Fortran 版本看起来越差。我不会因为我的业余 Fortran 技能而感到惊讶。出于同样的原因,我无法理解性能下降发生在哪里,甚至从哪里开始。你能帮忙评论一下吗?非常感谢您的宝贵时间!

System.f90

SysUtils.f90

Classes_TStringList.f90

Test program of the LoadFromFile/SaveToFile

【问题讨论】:

  • 也不完整。问题文本可能太多了。如果源在某处在线,则链接到它,如果不在某处在线。 (例如gist.github.com
  • 最重要的两个函数(可能是这里唯一重要的函数)- LoadFromFile 和 SaveToFile 已从您的问题中截断。如果没有看到它们,一种解释是 Delphi 使用缓冲 I/O 而 Fortran 版本没有。
  • @XichenLi - 看到你的代码后,我不认为缓冲 i/o 是解释,因为你在一次操作中将整个文件读入缓冲区。所以还有别的原因。我认为这就是分析的用武之地。了解代码在哪里花费时间的最好方法是分析它。从那里你可以看到你的 Fortran 版本是否一切都慢了 10 倍(即这是 Fortran 的错),或者你是否在你的实现中引入了瓶颈。
  • 这将在紧要关头工作,但要四处搜索以查看是否有支持您的编译器实现的检测或采样分析器。
  • @XichenLi - 如果你找不到合适的分析器,你可以用费力的方式来做。有几种方法。一种是思考 Fortran 和 Delphi 之间的根本区别并对其进行测试。示例 - 打印比较两个平均长度字符串 100,000 次的时间,看看这是否是罪魁祸首。或者自上而下。测试将 100,000 个字符串插入列表的时间。如果 Fortran 和 Delphi 的时间差异很大,请分别测试 insert 的每个部分并进行比较。但是好的分析工具可以让您不必深入寻找答案。

标签: string performance delphi memory-management fortran


【解决方案1】:

我相信最根本的区别将来自 Delphi 中“字符串”类型和 Fortran-90 中可变长度字符串的不同性质。

在 Delphi 中,String 是一种引用类型。不仅如此,它还是一个引用计数和修改时复制类型。

那是你写作的时候:

  var
    a, b: String;   
  begin
    a := 'The quick brown fox';
    b := a;

    b := b + ' jumped over the lazy dog.';
  end;

a 分配给 b 时,不会复制字符串字符。取而代之的是 ba 是现在引用相同字符串且引用计数为 2 的指针。

b 然后被修改时,只有在那个时候(由编译器)生成的代码才需要创建一个具有自己的引用计数的初始重复字符串 (1)并减少原始引用计数。

但是,简单地向列表中添加一个字符串显然不会修改它。

TStringList 读取文件内容时,会从文件中读取一个字符串。然后将字符串值添加到内部列表时,不会复制字符串本身,而是增加引用计数,这反映了即使“LoadFromFile”方法不再使用该字符串(因为它的内容已经替换为从文件中读取的下一个字符串)先前添加到内部列表项的字符串仍然有效。

LoadFromFile 然后必须初始化一个新字符串,准备好从文件中接收下一个字符串,但这是不可避免的。

不同之处在于,在 Fortran 版本中,除了在从文件中读取每个字符串时对其进行初始化之外,还必须在将项目添加到列表时复制这些字符串中的每一个。由于引用计数的字符串类型,这种字符串数据的复制在 Delphi 代码中被消除了。

因此,Fortran 代码的效率将不可避免地降低,而 Delphi 中引用计数的 String 类型的更高效率将对类的几乎每个领域产生影响——根据定义和设计——类的重“用户”这个字符串类型。

除了 Delphi 编译器与 Fortran 的内存管理性能或代码生成效率方面的任何其他相对差异之外,这将超出和补充。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 2012-11-19
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    相关资源
    最近更新 更多