string - 为什么 Fortran 版本的 Delphi 的 TStringList 的业余实现比 Delphi 的内置版本低 10 倍?

标签 string performance delphi memory-management fortran

学习最新Fortran的OO特性, 一个 Fortran Delphi 的版本的TStringList写在下面并链接在下面(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

最佳答案

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

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

那是你写的时候:

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

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

一个 分配给 b 没有字符串字符的复制。而是 b 一个 是现在引用相同字符串且引用计数为 2 的指针。

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

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

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

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

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

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

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

关于string - 为什么 Fortran 版本的 Delphi 的 TStringList 的业余实现比 Delphi 的内置版本低 10 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11368809/

相关文章:

python - 用python中字符串中的另一个单词替换单词

java - 从远程文件读取字符串 - Java

windows - socket 乒乓性能

c++ - 使用 SDL 逐像素绘图会导致性能不佳?

performance - HashMap 和 Vec 之间的内存高效转换

delphi - 如何防止快捷方式在Delphi中碰撞/交互?

c - 如何检查 fscanf() 在 C 中返回有效字符串?

c++ - 在 Xcode 4.2 中包含 <string> 未找到编译错误

delphi - 如何在运行时隐藏组件?

arrays - 通过带有起始和长度说明符的引用传递静态/动态数组的切片