Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Class Delphi:将数据存储在类与记录中,减少内存使用_Class_Delphi_Oop_Memory - Fatal编程技术网

Class Delphi:将数据存储在类与记录中,减少内存使用

Class Delphi:将数据存储在类与记录中,减少内存使用,class,delphi,oop,memory,Class,Delphi,Oop,Memory,当应用程序运行时,我有很多数据要在内存中存储、读取和修改。数据可以比作一棵树,其中每个节点由有限数量的字符串和整数描述,并且有相当多的子元素。 目前,数据是使用类/对象存储的,如 TRootElement = class fName, fDescription: string; fPos: integer; /// etc end; fDocs: TObjectList; //list of TVariable = class(TRootElement) fClasses: TOb

当应用程序运行时,我有很多数据要在内存中存储、读取和修改。数据可以比作一棵树,其中每个节点由有限数量的字符串和整数描述,并且有相当多的子元素。 目前,数据是使用类/对象存储的,如

TRootElement = class
  fName, fDescription: string;
  fPos: integer;
  /// etc
end;

fDocs: TObjectList; //list of TVariable = class(TRootElement)
fClasses: TObjectList; // list of TClass=class(TRootElement)
目前程序占用的内存是不可接受的,因此我正在寻找解决方案来限制它

我的问题是:如果我用基于记录的体系结构替换当前的、面向对象的和基于对象的体系结构,消耗量会显著减少吗? 例如,常规记录可以包含:

TRootElement = record
  fType: TElemType; // enum: root, variable, class, etc ... 
  fName, fDesc: string; 
  // all the fields used by root elem and it's descendants there
end;
我应该用指向下一个/上一个元素的指针替换TList吗?因为我从不按索引访问列表的元素,我总是在整个列表中循环,这应该不是很难做到。。。不过,如果没有必要,我想避免

谢谢!
m、

将类更改为记录将减少内存使用,但随着类或记录中字段数量的增加,节省的意义会降低。一个类和相应记录之间的大小差正好是四个字节,这就解释了一个类所持有但记录中不存在的大小差。当考虑权衡时,这种差异通常是微不足道的:为了节省四字节,你放弃继承、多态、数据隐藏和其他面向对象的特性。(Delphi的新“records with methods”可能会缓解其中一些问题,但如果您只有Delphi 2005,您还没有该功能。)

事实上,如果这四个字节真的对你的程序产生影响,那么你可能有一个更大的问题要解决。只需在树中添加另一个节点,就可以消除四字节的节省。有了足够大的数据集,无论您将任何一个节点设置得多小都无关紧要,因为您无论如何都无法将它们全部保存在内存中。您需要研究某种缓存方案,因此只有一些节点保存在内存中,其余节点保存在其他位置,例如文件或数据库中

如果将当前列表替换为双链接的节点列表,您可能会看到内存使用量增加,因为现在每个节点都在跟踪其下一个和上一个邻居,而在
之前,TObjectList
自己管理所有这些

目前程序消耗的内存是不可接受的

不可接受的含义是什么?你量过了吗?事实是什么(对象的数量、对象的大小、使用的内存)

如果你的程序有内存泄漏,你有没有和FastMM联系?如果不是的话,这是你应该做的第一件事

如果列表经常增长,那么可能是内存碎片问题。使用列表的容量属性(如果可能)。在这种情况下,链表可能会有所帮助,但链表需要比TList更多的内存(如果使用了容量)。看见 有关如何检查它的更多信息


对于Delphi来说,如果你能像Kornel所说的那样设置字符串的限制,那就真的很重要了。ansistring有一些内部开销,还有额外的开销。但是,始终分配短字符串,即使未使用

如果内存非常紧张,则自行分配字符串更为合理,特别是在数据相对不可变的情况下。然后简单地分配一个大的块,并将所有字符串放在其中,前缀是16位左右的长度

较低级别的技巧,如简单地重复(某些)字符串,也可以节省大量存储空间

请注意,Rob的record vs class讨论只有在您设法以非常便宜的成本在内存中静态实例化类时才会出现,而您可能不会这样做。这是因为您可以使用记录数组。否则,它始终是引用类型这一事实会导致heapoverhead和-slack(fastmm,16字节粒度)

我建议不要使用TSTRIGLIST/TLIST/TOBJECTLIST,因为在非常大的列表(数百万)中的插入删除可能是痛苦的,因为删除/插入是O(n),插入中间意味着移位一半的数据。这在20-100k和1M元素之间的某个位置会变得很痛苦,具体取决于您的访问模式

使用一个tlist列表,不要让每个tlist都变得太大,这已经是一个很好的解决方法

当我这样做时(对于2GB服务器内存仍为2000美元的OLAP集群),我甚至一度使用指针中的对齐位来存储分配的大小类。但我不建议这样做:-)


当然,64位FPC也是一种选择。我在不到一个小时的时间内就让上述32位解决方案的核心服务器部分在64位下工作。

与绝大多数IDE相比,仅加载10兆字节的所有PHP5元数据的内存增加实际上是相当不错的

如果这真的值得你付出努力,我会从字符串文字合并开始

将所有字符串放入全局表(或字典),并从所有字符串中指向该表(或字典)

您可以更进一步,因为PHP5语言和库是非常静态的:将整个数据结构从动态转换为静态常量(使用记录)和所有索引枚举类型

您可以做的是将所有字符串设置为ResourceString或string常量,并查看Delphi编译器是否可以为您执行文字合并

我刚刚注意到,您还加载了所有PHP5内容的文档。那占了相当多的内存。
您可能希望将这些数据加载到压缩流中。

哪个版本的Delphi会有所帮助。如果您向我们显示1.8 MB基本文本文件中的一部分数据,那么我们可能会给您提供一些更好的答案。往下看,该应用程序似乎包含一个“代码完成”解析树。我会考虑把这些东西存储在一个内存映射文件中。