Delphi 查找最大的可用内存块
当它变得碎片化时,有时会出现内存不足的问题 有可能找到最大的空闲内存块吗? 我使用Delphi2007和FastMM。在Windows XP上开发Windows 2003上运行的应用程序 问候 编辑: 我可以添加应用程序在Windows server 2003 x64上具有32 GB内存的服务器上运行的信息。但该应用程序是32位应用程序,因此理论上每个实例的最大分配内存为2GB。多个实例同时运行。我不认为总的物理内存太少。我猜当应用程序启动时,会有一个32位的虚拟内存空间。在运行时,这可能会变得过于零碎 我还找到了FastGetHeapStatus方法,该方法返回一个带有一些字段的THeapStatus,用于释放内存。也许我可以用这些 EDIT2: 我找到了这个。 代码是C,但可能可以翻译成Delphi。不,这是旧Turbo Pascal中的“maxavail”,这是一个经常被请求的特性,但不幸的是,在多用户、多任务环境中,这是一个无用的概念 heapmanager可以知道它自己维护的内存中最大的块,但通常是小的,因为大的块直接从windows分配(并返回到windows) 而逐步尝试分配更大数据块的方案将失败,因为操作系统将授予请求,即使这意味着要用磁盘交换请求(这是您不想要的)。对于尝试通过windows api调用挖掘此类值的技巧也是如此 整个受保护模式环境的基础是共享内存,每个应用程序只使用所需的内存。忽视这一点,假装一切都像在Dos下一样,只会让同时运行多个应用程序的人产生大量抱怨 如果您的应用程序确实依赖于此,请使用安全(小)默认值将其设置为配置设置(启动时为某个对象分配多少内存)。如果这真的很重要,请在安装过程中与用户对质Delphi 查找最大的可用内存块,delphi,memory-management,Delphi,Memory Management,当它变得碎片化时,有时会出现内存不足的问题 有可能找到最大的空闲内存块吗? 我使用Delphi2007和FastMM。在Windows XP上开发Windows 2003上运行的应用程序 问候 编辑: 我可以添加应用程序在Windows server 2003 x64上具有32 GB内存的服务器上运行的信息。但该应用程序是32位应用程序,因此理论上每个实例的最大分配内存为2GB。多个实例同时运行。我不认为总的物理内存太少。我猜当应用程序启动时,会有一个32位的虚拟内存空间。在运行时,这可能会变得
当然,通过执行一些winapi调用并假设没有其他应用程序运行,可以始终使用启发式尝试来播种默认值。但最终决定权总是留给用户,特别是对于服务器应用程序。在虚拟内存系统上,虚拟地址空间意味着虚拟页面可以映射到任何地方。您不需要大的连续物理内存块。如果您的虚拟地址空间存在碎片问题,那么您可能需要不同的内存管理策略 但是,大多数选项都要求应用程序代码在某种程度上了解内存管理策略。我不相信有一个快速修复这个问题-你可能是合理的大手术来修复它。这些选项都不容易实现,您必须找到最适合您的特定情况的选项 我可以看到的主要选项有:自定义内存分配器、涉及AWE的东西(见下文)或在应用程序中重建内存分配策略 选项1:自定义内存分配器 <>自定义内存分配器在C和C++循环中并不少见。您可能能够实现类似的功能。您有两种可能:
- 构建一个内存分配器,其机制是尝试将相邻的空闲块合并为单个较大的块(您可以将此作为尝试从失败的内存分配中恢复的一部分来运行)。这可能允许您透明地管理内存,而无需应用程序知道。实现这一点需要技巧和技术,但可能是可行的。
这种方法的主要好处是,它是唯一不需要您更改现有应用程序代码的方法。缺点是它不能保证有效;合并操作仍然可能无法整合足够大的内存块以满足请求。合并操作还可能导致运行时应用程序响应出现明显暂停 - 您可能需要以允许压缩数据结构的方式构建应用程序。这需要您维护支持移动对象的句柄,即双间接机制。我猜可能有一个或相当少的不同数据结构导致了这个碎片化问题,因此有可能在应用程序中本地化任何重新架构的工作
- 您可以使用此机制作为管理数据的固有部分,为数据结构构建管理器
- 如果可以将数据结构中的项目与页面边界相匹配,则可以将其用作整合内存的方法
function GetLargestFreeMemRegion(var AAddressOfLargest: pointer): LongWord;
var
Si: TSystemInfo;
P, dwRet: LongWord;
Mbi: TMemoryBasicInformation;
begin
Result := 0;
AAddressOfLargest := nil;
GetSystemInfo(Si);
P := 0;
while P < LongWord(Si.lpMaximumApplicationAddress) do begin
dwRet := VirtualQuery(pointer(P), Mbi, SizeOf(Mbi));
if (dwRet > 0) and (Mbi.State and MEM_FREE <> 0) then begin
if Result < Mbi.RegionSize then begin
Result := Mbi.RegionSize;
AAddressOfLargest := Mbi.BaseAddress;
end;
Inc(P, Mbi.RegionSize);
end else
Inc(P, Si.dwPageSize);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
BaseAddr: pointer;
MemSize: LongWord;
begin
MemSize := GetLargestFreeMemRegion(BaseAddr);
// allocate dynamic array of this size
SetLength(fArrayOfBytes, MemSize - 16);
Caption := Format('Largest address block: %u at %p; dynamic array at %p',
[MemSize, BaseAddr, pointer(@fArrayOfBytes[0])]);
end;