Zvětšení dostupné paměti 32bit programů v Delphi

vložil Radek Červinka 19. září 2014 23:09

Jednoho krásného dne Váš program zjistí, že trpí nedostatkem paměti. Přirozeným krokem je přechod na 64bit aplikace, ale existuje i jiná možnost. U EXE (resp. PE souboru) se dá specifikovat flag IMAGE_FILE_LARGE_ADDRESS_AWARE. Tento flag byl původně určen pro speciální mód 32bit Windows, kdy místo normálních cca 2GB paměti pro 32bit proces nabízel celých úžasných 3GB volné paměti. Praktická využitelnost tedy nic moc, protože tento mód Windows se moc nepoužíval.

Situace se obrátila s příchodem 64bit Windows (jen aby nedošlo k nedorozumnění - dávejte pozor kdy mluvím o 32bit procesu, kdy o 32bit Windows a kdy o 64bit Windows).

64bit Windows kromě možnosti 64bit aplikací (které mají dostupnou paměť prakticky bez omezení) vylepšují podporu 32bit aplikací v uvedeném módu. Taková aplikace dostane do vínku místo klasických 2GB nebo 3GB z předchozího módu pěkných skoro celých 4GB paměti - což není vůbec špatné. Doufám, že je jasné, že je vhodné mít dostatečnou fyzickou paměť, jinak to moc nemá smysl.

Upozorňuji, že následující není vhodné pro staré verze Delphi, které na to vážně nejsou připraveny. Jako minimální bych tak odhadoval D2007. Pokud máte něco od cca XE (tipuji díky přípravám na 64bit) nebo XE2 (tam určitě k vůli podpoře 64bit) tak by to mělo být OK. Pokud mi nevěříte ohledně starých verzích, tak určitě použijte FastMM (a to v nějaké rozumné verzi) a něco dejte na dobročinnost, třeba se na Vás štěstí usměje.

Celý trik je v {$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}, což dá linkeru informaci o nastavení flagu PE souboru. Jak jistě víte, SetPEFlags je jednocestný - cokoliv se přes něj nastavuje je OR s dalšími volbami (některé se přímo nastavují v Options projektu) a není cesty zpět. Ideálně nastavit v DPR.

program Project36;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

var
  m: TMemoryStatusEx;
  p: Pointer;

begin
   FillChar(m, SizeOf(m), 0);
   m.dwLength := SizeOf( m );

   try
     repeat
       GetMem(p, MAXINT div 100);
       FillChar(m, SizeOf(m), 0);
       m.dwLength := SizeOf( m );
       GlobalMemoryStatusEx(m);
       writeln(m.ullAvailVirtual, ' ', Format('%p', [p]));
     until false;
   except

   end;
   readln;

end.

Pár poznámek: FastMM (tj. def. paměťový manažer Delphi) automaticky alokuje paměť (resp. nejméně velké bloky - dříve jsem psal o způsobu přidělování ve FastMM) shora dolů (pokud máte samostatný FastMM tak je tam na to option, který je ale ve verzi z Delphi automaticky nastaven). To znamená, že nejdříve bude přidělena paměť ze zadní části adresového prostoru, což v důsledku má pozitivní vliv na případné chyby z důvodu vysokých adres (a nejen to).

V uvedeném programu se opakovaně vypisuje dostupná virtuální paměť a alokují se velké bloky dokud paměť nedojde. Zároveň se vypisuje adresa přiděleného fláku paměti (pro ověření TOP-DOWN alokace). Jen pro jistotu: při Out-of-memory není dostupná paměť nula, ale něco pod velikost požadovaného bloku. Vyzkoušejte si běh s nastavením flagu i bez něho. A samozřejmě vše je bez záruky.

Tagy: , , , ,

Praxe

Komentáře

20.9.2014 19:56:05 #

tomk

No joo, a ted jdu na jih :)

To neni ironie. Opravdu mi to funguje (XE2 + Win7 64). A opravdu jsem to dodnes nevedel a koukam jako lekarnik Sofr z Podoli.

Bez flagu: 2059616256 7DB30010
S flagem: 4207099904 FEB30010

A to se vyplati. Diky, Radku.

tomk

22.9.2014 10:08:36 #

mitzi

Tak D2007 se k tomu neznaji.

mitzi

22.9.2014 10:22:33 #

radekc

K čemu? K té konstantě? Tak si najdi její hodnotu na webu, je to normálně číslo.

radekc

22.9.2014 10:55:51 #

radekc

Aha teď jsem to zkoušel v D2007: konstantu zná, ale nezná TMemoryStatusEx, případně GlobalMemoryStatusEx - dají se najít na webu.

radekc

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců