小编lke*_*ler的帖子

为什么Delphi中字符串的内存过多?

我正在阅读一个大文本文件,其中有140万行,大小为24 MB(平均每行17个字符).

我正在使用Delphi 2009,文件是ANSI但在读取时会转换为Unicode,所以你可以说转换后的文本大小为48 MB.

(编辑:我发现了一个更简单的例子......)

我正在将此文本加载到一个简单的StringList中:

  AllLines := TStringList.Create;
  AllLines.LoadFromFile(Filename);
Run Code Online (Sandbox Code Playgroud)

我发现数据行似乎占用了比48 MB更多的内存.

实际上,他们使用155 MB的内存.

我不介意Delphi使用48 MB甚至多达60 MB允许一些内存管理开销.但155 MB似乎过度.

这不是StringList的错误.我之前尝试将行加载到记录结构中,我得到了相同的结果(160 MB).

我没有看到或理解什么可能导致Delphi或FastMM内存管理器使用3倍的内存量来存储字符串.堆分配不能低效,可以吗?

我调试了这个,并尽可能地研究它.任何关于为什么会发生这种情况的想法,或者可能有助于减少过量使用的想法都会受到高度赞赏.

注意:我使用这个"较小"的文件作为示例.我真的想加载一个320 MB的文件,但是由于这个多余的字符串要求,Delphi要求超过2 GB的RAM和内存不足.

Addenum:Marco Cantu刚刚发布了关于Delphi和Unicode的白皮书.Delphi 2009将每个字符串的开销从8个字节增加到12个字节(对于字符串的实际指针,可能还有4个字节).每17x2 = 34字节行额外增加16个字节,几乎增加了50%.但我看到超过200%的开销.150%的额外费用是多少?


成功!!感谢大家的建议.你们都让我思考.但是我必须给Jan Goyvaerts一个答案,因为他问:

你为什么使用TStringList?文件真的必须作为单独的行存储在内存中吗?

这使我得到了解决方案,而不是将24 MB文件作为140万行StringList加载,我可以将我的行分组到我的程序知道的自然组中.因此,这导致127,000行加载到字符串列表中.

现在每行平均190个字符而不是17个.每个StringList行的开销是相同的,但现在有更少的行.

当我将其应用于320 MB文件时,它不再耗尽内存,现在加载的RAM不到1 GB.(它只需要大约10秒钟加载,这是非常好的!)

将有一些额外的处理来解析分组的行,但在每个组的实时处理中不应该注意到它.

(如果你想知道,这是一个家谱程序,这可能是我需要的最后一步,它允许它在不到30秒的时间内在32位地址空间中加载大约一百万人的所有数据.所以我'我们仍然需要一个20秒的缓冲区才能将索引添加到数据中,以便显示和编辑数据.)

delphi memory-management utf-16 delphi-2009 fastmm

10
推荐指数
3
解决办法
4955
查看次数

Windows开发人员如何最轻松地使他的软件在Wine下运行良好

我的许多用户都告诉我他们想在Wine下的Linux机器上运行我的软件.

但我是一名几乎没有Linux经验的Windows开发人员.

现在我可以花一两个月安装Linux,学习Linux,安装Wine,学习Wine,并彻底确保我的应用程序在Wine下运行良好.但我仍在为Windows开发,所以我现在不想花太多时间从开发开始.

那么,如果不花太多精力让我的程序在Wine下运行,我能做些什么呢?


我确实找到了关于在Wine下运行应用程序的常规帮助.

unix linux cross-platform wine

10
推荐指数
2
解决办法
841
查看次数

如何在Delphi中找到"List index out of bounds"错误的位置

在Delphi 2009中,我的程序现在生成"List index of bounds"错误.它会生成一个弹出框:

alt text http://www.beholdgenealogy.com/img/boundserror.gif

我正在使用"调试"构建配置,该配置已启用所有运行时错误检查.但这并没有在错误发生之前捕获错误.

是否有任何简单的方法可以在我的程序中找到此错误的来源,而无需通过反复试验来缩小断点并缩小范围?

delphi error-handling bounds-checker

10
推荐指数
3
解决办法
2万
查看次数

在Delphi中替换可视组件的最佳方法

在Delphi表单中,我想将一个可视组件替换为另一个.示例:我想用第三方软件包中的ElPanel替换Panel组件.

我希望将第一个组件的所有相同属性和事件转移到新组件,并且属于第一个组件的所有组件(例如工具栏,备忘录,状态栏等)最终放在新组件上他们在第一个的确切位置.

除了将新组件添加到表单并精心地将每个属性,事件和组件逐个转移到表单之外,还有最好/最简单的方法吗?

delphi components replace

9
推荐指数
3
解决办法
5766
查看次数

在Delphi中解析一行的最快方法是什么?

我有一个庞大的文件,我必须逐行解析.速度至关重要.

一行示例:

Token-1   Here-is-the-Next-Token      Last-Token-on-Line
      ^                        ^
   Current                 Position
   Position              after GetToken
Run Code Online (Sandbox Code Playgroud)

调用GetToken,返回"Here-is-the-Next-Token"并将CurrentPosition设置为令牌最后一个字符的位置,以便为下次调用GetToken做好准备.令牌由一个或多个空格分隔.

假设文件已经在内存中的StringList中.它很容易适合内存,比如200 MB.

我只担心解析的执行时间.什么代码将在Delphi(Pascal)中产生绝对最快的执行?

delphi parsing pascal token

9
推荐指数
1
解决办法
1万
查看次数

Delphi 2009最高效的Unicode哈希函数

我需要Delphi 2009中可能的最快哈希函数,它将从Unicode字符串创建散列值,该字符串将随机分配到存储桶中.

我最初从GpStringHash 开始使用Gabr的HashOf函数:

function HashOf(const key: string): cardinal;
asm
  xor edx,edx     { result := 0 }
  and eax,eax     { test if 0 }
  jz @End         { skip if nil }
  mov ecx,[eax-4] { ecx := string length }
  jecxz @End      { skip if length = 0 }
@loop:            { repeat }
  rol edx,2       { edx := (edx shl 2) or (edx shr 30)... }
  xor dl,[eax]    { ... xor Ord(key[eax]) }
  inc eax         { inc(eax) }
  loop …
Run Code Online (Sandbox Code Playgroud)

delphi unicode hash assembly delphi-2009

9
推荐指数
3
解决办法
3130
查看次数

如何使用Delphi获取与文件扩展名相关联的程序名称?

我需要获取当前与当前用户的文件扩展名相关联的程序的名称.如果右键单击文件并选择属性,那么我需要的是"打开方式"行右侧的程序名称.

例如,对于".xls",我希望能够得到答案"Microsoft Office Excel",或者用户拥有的任何程序作为打开.xls文件的默认程序.

我已经确定它并不像进入HKEY_CLASSES_ROOT并选择它那么容易,因为它也可以在HKEY_LOCAL_MACHINE或HKEY_CURRENT_USER或HKEY_USERS中指定.

也许我需要知道的是Windows用来确定这个以及如何到达每个位置的啄食顺序.当然,执行此操作的Windows API调用将是理想的.

这是一个类似的问题: 如何使用Delphi从文件扩展名获取图标和描述?但是这个问题只回答了如何获得扩展的描述和相关程序的图标.我找不到扩展它的方法来获取相关程序的名称.

我正在使用Delphi 2009,需要一个适用于Windows XP,Vista和7的解决方案.


谢谢大家的答案.

我认为可执行文件的名称毕竟不在注册表中.在广泛浏览了将提供名称的Windows API之后,我找不到一个.

我认为Mef的答案是最好的.从程序可执行文件中包含的信息中获取可执行文件的名称.

windows delphi registry file-type file-association

9
推荐指数
4
解决办法
1万
查看次数

如何使用(在Delphi中)创建文件(或文件集)的数据库格式?

我有许多不同程序创建的数据文件.有没有办法确定用于创建数据文件的数据库和数据库版本.

例如,我想确定哪些文件是从Microsoft Access,dBASE,FileMaker,FoxPro,SQLite或其他文件创建的.

我真的只是想以某种方式快速扫描文件,并显示有关它们的信息,包括源数据库和版本.

作为参考,我正在使用Delphi 2009.

database delphi identify file-structure

9
推荐指数
1
解决办法
8594
查看次数

带应用程序内购买的Delphi XE2 iOS应用程序

我是delphi开发人员,目前正在使用Delphi XE2和Firemonkey开发iPhone和iPad应用程序.

Apple要求我在一个应用程序中整合所有提交的应用程序(大约10个),并提供应用程序内购买.对于不同类型的用户来说,它们是非常不同的应用程序,但仍然是Apple评论者想要它的方式.填写上诉并丢失.我无能为力,以避免IAP.

关于firemonkey iOS应用程序的信息非常少,而且找不到任何与应用内购买相关的信息.

应用程序内购买使用Apple的StoreKit框架,我相信它包含在freepascal iPhoneAll单元中,但我不知道如何在Pascal中设置和使用它.没有关于它的文件(仅针对目标c).

我非常担心过去几个月开发的辛苦工作因使用Delphi XE2(甚至是pascal源上的Xcode)的API而无法实现.

任何帮助将非常感谢.谢谢!

delphi app-store in-app-purchase delphi-xe2 firemonkey

9
推荐指数
0
解决办法
2238
查看次数

如何在Delphi中获取屏幕的可用坐标

使用Screen.DesktopHeight和Screen.DesktopWidth,我可以获得"虚拟"桌面的大小,我相信它适用于一个或多个显示器.

我将应用程序的位置(顶部和左侧)和大小(高度和宽度)保存到注册表中.当它打开时,我想确保它完全可见,因为它可能已部分移动到可见区域之外,或者屏幕尺寸可能已经改变,例如通过屏幕设置或移除监视器.

我基本上可以用这段代码来做:

if MyForm.Width > screen.DesktopWidth then 
  MyForm.Width := screen.DesktopWidth;

if MyForm.Height > screen.DesktopHeight then 
  MyForm.Height := screen.DesktopHeight;

if (MyForm.Left + MyForm.Width) > screen.DesktopWidth then 
  MyForm.Left := screen.DesktopWidth - MyForm.Width;
if MyForm.Left < 0 then MyForm.Left := 0;

if (MyForm.Top + LogoAppForm.Height) > screen.DesktopHeight then 
  MyForm.Top := screen.DesktopHeight - LogoAppForm.Height;
if MyForm.Top < 0 then MyFormTop := 0;
Run Code Online (Sandbox Code Playgroud)

这没关系,除了它没有考虑通常(但不总是)在桌面底部的任务栏.因此,如果任务栏妨碍了我的应用程序窗口,我的应用程序就会变得模糊不清.

如何获取排除任务栏位置的屏幕的可用位置和大小设置?

delphi size taskbar position screen

8
推荐指数
3
解决办法
2万
查看次数