- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在读取一个包含 140 万行、大小为 24 MB 的大型文本文件(平均每行 17 个字符)。
我使用的是 Delphi 2009,该文件是 ANSI,但在读取时会转换为 Unicode,因此您可以公平地说,转换后的文本大小为 48 MB。
(编辑:我找到了一个更简单的例子......)
我正在将此文本加载到一个简单的 StringList 中:
AllLines := TStringList.Create;
AllLines.LoadFromFile(Filename);
我发现数据行占用的内存似乎比 48 MB 多得多。
事实上,它们使用 155 MB 内存。
我不介意 Delphi 使用 48 MB 甚至多达 60 MB,以允许一些内存管理开销。但 155 MB 似乎太多了。
这不是 StringList 的错误。我之前尝试将这些行加载到记录结构中,并且得到了相同的结果 (160 MB)。
我不明白也不明白是什么导致 Delphi 或 FastMM 内存管理器使用存储字符串所需内存量的 3 倍。堆分配不可能那么低效,不是吗?
我已经对此进行了调试并尽我所能进行了研究。任何关于为什么会发生这种情况的想法,或者可能帮助我减少过度使用的想法将不胜感激。
注意:我使用这个“较小”的文件作为示例。我确实想加载一个 320 MB 的文件,但 Delphi 要求超过 2 GB 的 RAM,并且由于过多的字符串要求而导致内存不足。
附录:Marco Cantu 刚刚推出 a White Paper on Delphi and Unicode 。 Delphi 2009 将每个字符串的开销从 8 个字节增加到 12 个字节(加上指向字符串的实际指针可能还增加了 4 个字节)。每 17x2 = 34 字节行额外增加 16 字节,几乎增加了 50%。但我发现开销超过 200%。额外的 150% 可能是什么?
<小时/>成功!!感谢大家的建议。你们都让我思考。但我必须承认 Jan Goyvaerts 的回答,因为他问:
...why are you using TStringList? Must the file really be stored in memory as separate lines?
这让我找到了解决方案,我可以将我的行分组到我的程序知道的自然组中,而不是将 24 MB 文件作为 140 万行 StringList 加载。因此,这导致 127,000 行加载到字符串列表中。
现在每行平均有 190 个字符,而不是 17 个。每 StringList 行的开销是相同的,但现在行数少了很多。
当我将此应用于 320 MB 文件时,它不再耗尽内存,并且现在加载到不到 1 GB 的 RAM 中。 (而且加载时间只需要10秒左右,非常不错!)
解析分组行时会进行一些额外的处理,但在每个组的实时处理中应该不会被注意到。
(如果您想知道,这是一个家谱程序,这可能是我需要让它在 30 秒内加载 32 位地址空间中约 100 万人的所有数据所需的最后一步。因此,我仍然有 20 秒的缓冲区可以使用,以将索引添加到数据中,这是允许显示和编辑数据所必需的。)
最佳答案
您要求我亲自在这里回答您的问题。我不知道您看到如此高的内存使用率的确切原因,但您需要记住 TStringList 所做的不仅仅是加载文件。其中每个步骤都需要内存,这可能会导致内存碎片。 TStringList 需要将文件加载到内存中,将其从 Ansi 转换为 Unicode,将其拆分为每一行一个字符串,并将这些行填充到一个将被重新分配多次的数组中。
我的问题是你为什么使用 TStringList?文件真的必须作为单独的行存储在内存中吗?您要修改内存中的文件,还是只显示其中的一部分?将文件作为一大块保存在内存中,并使用与您想要的部分匹配的正则表达式扫描整个文件,这比存储单独的行更有效。
另外,必须将整个文件转换为 Unicode 吗?虽然您的应用程序是 Unicode,但您的文件是 Ansi。我的一般建议是尽快将 Ansi 输入转换为 Unicode,因为这样做可以节省 CPU 周期。但是,当您有 320 MB 的 Ansi 数据将保留为 Ansi 数据时,内存消耗将成为瓶颈。尝试在内存中将文件保留为 Ansi,并且仅将要向用户显示的部分转换为 Ansi。
如果这个 320 MB 的文件不是您要从中提取某些信息的数据文件,而是您要修改的数据集,请考虑将其转换为关系数据库,并让数据库引擎担心如何管理这个巨大的文件RAM 有限的数据集。
关于delphi - 为什么 Delphi 中的字符串内存过多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/312118/
请在标记为重复之前阅读。 我正在创建一组依赖智能卡进行身份验证的应用程序。到目前为止,每个应用程序都单独控制智能卡读卡器。几周后,我的一些客户将同时使用多个应用程序。因此,我认为创建一个控制身份验证过
我想设置一个小程序,从数据库中检索信息,然后根据请求将该信息分发给另一个程序。例如,一个名为“Master”的程序将从数据库中检索数据并创建一个对象集合(列表、数组等,无论哪种效果最好),然后一个名为
我有两台电脑,都装有 XE2。我以为我在两者上安装了相同的安装,但在其中一个上安装第 3 方软件包时遇到问题,而另一个则正常。 无论如何,我希望两者都一样。最简单的人可能只是通过移入我的 Dropbo
有冲突吗? 最佳答案 所有新版本的 Delphi 始终可以安全地安装到旧版本的下一个版本。 每个新版本都应安装在其自己的目录中。 如果您要安装多个版本,请始终先安装最旧的版本,然后再安装最新版本。 我
快速提问:如果我从代码中删除 // 或 (* *) 中的注释,Delphi 2007 的执行时间会受到影响吗?最终结果是一个可能包含数千行注释的 EXE 文件。 最佳答案 编译器会简单地忽略注释,并且
我必须对照另一个文件检查文件的每一行。 如果第二个文件中存在第一个文件中的一行,则必须删除它。 现在,我正在使用2个列表框,并且“对于listbox1.items.count-1可以开始...” 我的
我正在尝试在访问数据库中添加一些数据。但是我有麻烦,因为这会返回错误: ADOQuery1 missing sql property 实现了对代码的几次修改,到目前为止没有任何效果。 我究竟做错了什么
我用Delphi 5编写了一个程序,在Windows 8 32位PC上可以正常运行。我发现在Windows 7 64位笔记本电脑上运行它最终会导致reallocmem错误,而该错误在32位PC上不会发
看来这是我需要的工具,用于提取XML并与TClientDataset连接。我已经在几篇文章和文档中看到了它,但是我无法在XE2组件列表中找到它-在任何地方!应该在哪里?是否在可能未安装的可选软件包中?
我正在寻找一个非常通用的TDBTree组件,我想听听一些建议。我正在特别寻找一种显示主记录和“ n”个链接表记录的记录。 (我的意思是来自各个表的记录)。例如,TDBTree将钩接到主表,明细表1,附
我需要将按钮制作成旋转三角形的形状(或者说是任何多边形)。谁能提供任何建议? 最佳答案 查看Win32 API CreatePolygonRgn()和SetWindowRgn()函数,以创建一个HRG
你好专家 我的JvPasswordForm1有一个旧的JVC组件。 似乎该组件不再存在:它替换为哪个组件? 重新获得 最佳答案 尝试查找TJvLoginDialog,TjvPassword已合并到其中
几天前,我已经设置了我的开发环境(在装有Win 7的VM和域上的用户的VM上安装了delphi 2009),并安装了我的组件(jedi's,devExpress,ADS等)。 今天,我启动机器,打开d
开始对控件进行子分类的正确位置/时间是什么? 恢复原始窗口proc的正确时间是几点? 现在我在表单创建过程中子类化: procedure TForm1.FormCreate(Sender: TObje
有人可以给我一些有关如何登录访问的网页(使用任何网络浏览器)的指示吗?我应该建立一个全球代理....钩住网络....吗?我需要记录的只是页面地址,而不是其中包含的信息。 我正在使用Delphi。 谢谢
我创建了一个像 TMyClass = class(TObject) private FList1: TObjectList; FList2: TObjectList; public end;
我有一个BPG文件,我已对其进行修改以用作我们公司的自动构建服务器的make文件。为了使其正常工作,我必须进行更改 用途*用途 'unit1.pas'中的unit1 * unit1 'unit2.pa
我将Delphi 7代码迁移到了Delphi XE4。我在Delphi XE4的LoadFromStram方法中遇到错误,但对于Delphi 7来说也可以正常工作。 错误: First chance
我正在尝试学习一些新技巧,以便更好地组织我在 Delphi 中的单元中的一些源代码。 我注意到我访问的一些函数或方法似乎是类中的类,但是我还没有成功地在类中创建一个工作类,虽然它编译得很好,但在执行代
我有一个包含许多类的大单元,现在我想通过将某些类分成新的单元来重构该单元。 我不得不承认我缺乏使用Delphi内置IDE功能的经验。利用内置功能“查找|查找对类型的本地引用”并没有多大帮助,因为类方法
我是一名优秀的程序员,十分优秀!