- 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/
我在 JBoss 6 上使用 JSF 2。我制作了一个示例应用程序,它使用 JSF 作为 View ,使用 EJB 作为逻辑,使用 JPA 作为持久性。 JSF 中的 bean 具有 RequestS
我打开气流并检查了连接,然后发现背后有太多连接。 关于如何杀死那些我不使用的想法,或者我很想知道运行它的最低conn_id的任何想法。 建筑 LocalExecutor(与其他经纪人不同) Postg
我收到错误 style.css:1 GET https://www.example.com/cs_CZ净::ERR_TOO_MANY_REDIRECTS 可能与我的 htaccess 有关吗? Rew
我收到错误 style.css:1 GET https://www.example.com/cs_CZ净::ERR_TOO_MANY_REDIRECTS 可能与我的 htaccess 有关吗? Rew
我正在 Android 中开发一个应用程序,我有以下 XML 布局:
我有 5 个类用作运算符: TurnOn , TurnOff , PushBox , Exit , Enter 对于每种类型,我都有一个包含该类型描述的字符串。 例如: class Places {
我们在使用 lettuce redis 库时遇到了这个具体问题。我们收到太多 RedisCommandTimeoutException。我们在 redis-cli 中设置了 2 秒的超时,在 redi
在 Controller 类文件中,大多数方法函数都包含try/catch块,如下所示: try { $stmt = $this->prepare($sql); $st
我读到这个page附加很多元素是不好的做法,我应该在循环的每次迭代期间构建一个字符串,然后将 DOM 元素的 HTML 设置为该字符串。在循环中使用过多的 HTML 是否也是如此? 我有一个解析 JS
在我的应用程序日志上运行 logcat 时,我看到很多 GC_FOR_ALLOC 而没有 GC_CONCURRENT 消息。我知道我有内存泄漏,但在堆栈和其他站点的任何地方,logcat 消息都有很多
当我检查我的 Tomcat 应用程序管理器时,我发现我的 session 太多(超过 4600): 为什么会这样?这可以链接到已部署的应用程序,还是它已经运行了很长时间? 最佳答案 这可能有多种原因,
所以我试图在一个 div 中运行 3 个 float ,但我遇到了这个问题。 http://jsfiddle.net/sPUjQ/101/ 点我 每当我运行两次 float 时,背景颜色会保持不变,但
为什么在使用 http_build_query 函数构建查询字符串时,它会将方括号 [] urlencode 到值之外,如何摆脱它? $query = array("var" => array("fo
在一个过程中,我需要使用许多 if-else 条件来决定列的值。该脚本以 FOR rec IN (SELECT....) LOOP Begin 并决定许多不同的值 rec 子记录可以在每次迭代中获得。
我们基于 Java 的服务器应用程序报告异常长的类加载时间: # jstat -class 10625 1000 Loaded Bytes Unloaded Bytes Time 4
我正在使用 Kraken.js 开发一个应用程序并管理我决定使用的 session :connect-mongo。 我有这样的设置: 'use strict'; var session = requi
我在 iPad 应用程序中有 180 个 UILabels(UITableViewCells 的 subview ),每个 UILabel 的宽度为 155 X 155,并且每个包含大量 Unicod
所以基本上,如果我将 JPanel 放入使用 GridBagLayout 的 JPanel 中,并使用 setPreferredSize 限制大小>,最终它达到了无法容纳所有这些的地步,并且它表现出附
我目前使用的是 Play 2.2.1,在白天运行生产 Web 应用程序后,我的日志中开始出现以下错误。似乎我的连接已用完/我一定没有正确关闭某些东西,但我似乎无法弄清楚它是什么。 2014-02-11
所以我几乎完成了我的元素,我打算创建一个完整的网页 slider 作为我网站的背景主题,并且它运行完美! 问题是它的垂直拉伸(stretch)太长,您可以向右滚动(您不应该那样做)而且我不知道为什么它
我是一名优秀的程序员,十分优秀!