Velikosti EXE u jednotlivých verzí Delphi

vložil Radek Červinka 13. ledna 2011 01:06

Narazil jsem na takovou debatu o velikosti EXE u prázdné VCL aplikace. A jelikož jsem si chtěl upřesnit, jak je to s tou velikostí u jednotlivých verzí Delphi, strávil jsem cca 45 minut vytvářením prázdných aplikací a porovnáváním pomocí JCL Project Analyzeru, který je součástí instalace JCL.

Předem říkám, že si myslím, že velikost EXE není v dnešní době až tak podstatná, jelikož díky stránkování Windows a mapování souborů do paměti jsou v paměti jen opravdu používané části a zde se navíc pohybujeme v malém rozmezí. To platí jen tehdy, pokud nějaký inteligent nepoužijete EXE packer jako je UPX nebo PECompact. V tom případě nejen opravdu efektivně zabráníte uvedenému mechanismu jelikož celý program se musí rozbalit do paměti (pravda některé sekce PE souboru některé PE packery berou v potaz - ale není to pravidlem a na výsledku to moc nemění), ale navíc i vyloučíte sdílení kódu mezi více instancemi programu, takže v důsledku je na tom uživatel mnohem hůře, viz. třeba Are there any downsides to using UPX to compress a Windows executable?. A ne, velikost pro stažení není důvod (dá se zabalit jinak), a velikost USB disku už vůbec ne.

JCL Project Analyzer

Ale nechme toho a zpět k našemu problému. Jelikož nemám nainstalované všechny možné verze Delphi je zde možnost pro doplnění - pokud máte někdo nainstalované chybějící verze a zároveň JCL s uvedeným expertem (je dostupný v menu Project - Analyze Project), můžete mi poslat výstup a připsat uvedené informace. Vytvoříte prázdnou VCL aplikaci a spustíte expert (lépe po Buildu).

Velikost výsledného souboru

  • Delphi 5 - 294 400
  • Delphi 7 - 368 128 (nemám tam JCL, takže zatím bez podrobností)
  • Delphi 2007 - 407 552 (manifest)
  • Delphi 2009 - 499 712 (manifest)
  • Delphi 2010 - 817 152 (manifest)
  • Delphi XE - 915 456 (manifest)
  • Delphi XE - 824 832 (manifest, bez aplikační ikony)

Vysvětlivka k poslednímu řádku: nový projekt obsahuje pěknou aplikační ikonu v různých velikostech (hold moderní Windows to prosazují) o velikosti cca 90K. Pokud ji nahradíte za menší tak je vymalováno.

Složení PE souboru

Jednotlivé sekce PE souboru (neboli EXE) pro jednotlivé verze (poslední řádek v analyzeru).

  • Delphi 5: Code: 251124, Data: 2482, Bss: 2077, Resource 13312
  • Delphi 2007: Code: 345142, Data: 5906, Bss: 19654, Resource 18432
  • Delphi 2009: Code: 398007, Data: 6488, Bss: 20881, Resource 53248
  • Delphi 2010: Code: 674037, Data: 7666, Bss: 21161, Resource 54784
  • Delphi XE (bez ikony): Code: 717700, Data: 7680, Bss: 21112, Resource 17920
  • Delphi XE: 717700, Data: 7680, Bss: 21112, Resource 108544 - ikona

V Delphi 2009 byl do resources přidán 33K soubor character.res. V Delphi 2010 je zvětšení způsobeno velkým rozšířením RTTI informací (např. pro tohle použití RTTI mi to za to stojí).

Dále uvedené soubory zde ke stažení pro vlastní analýzu (na stránce jsou zobrazeny jen některé): D5.txt, D2007.txt, D2009.txt, D2010.txt, DXE.txt

Delphi XE

Name         Size Group
--------- ------- -----------------
Controls  127 936 (CODE+ICODE+DATA)
Classes   106 900 (CODE+ICODE+DATA)
Forms      87 788 (CODE+ICODE+DATA)
Graphics   56 684 (CODE+ICODE+DATA)
SysUtils   56 044 (CODE+ICODE+DATA)
System     40 352 (CODE+ICODE+DATA)
Menus      40 284 (CODE+ICODE+DATA)
Character  37 400 (CODE+ICODE+DATA)
Variants   33 928 (CODE+ICODE+DATA)
Themes     22 720 (CODE+ICODE+DATA)
Project1   19 956 (CODE+ICODE+DATA)
ImgList    14 812 (CODE+ICODE+DATA)
Registry   12 112 (CODE+ICODE+DATA)
ActnList    9 100 (CODE+ICODE+DATA)
HelpIntfs   8 304 (CODE+ICODE+DATA)
Printers    7 680 (CODE+ICODE+DATA)
GraphUtil   7 304 (CODE+ICODE+DATA)
Windows     6 652 (CODE+ICODE+DATA)
TypInfo     6 004 (CODE+ICODE+DATA)
SyncObjs    5 440 (CODE+ICODE+DATA)
UxTheme     3 444 (CODE+ICODE+DATA)
Dialogs     2 728 (CODE+ICODE+DATA)
VarUtils    2 072 (CODE+ICODE+DATA)
IOUtils     1 388 (CODE+ICODE+DATA)
ExcUtils    1 364 (CODE+ICODE+DATA)
ExtCtrls    1 100 (CODE+ICODE+DATA)
Types       1 020 (CODE+ICODE+DATA)
ComCtrls      976 (CODE+ICODE+DATA)
FlatSB        920 (CODE+ICODE+DATA)
Contnrs       912 (CODE+ICODE+DATA)
SysConst      840 (CODE+ICODE+DATA)
TimeSpan      740 (CODE+ICODE+DATA)
Consts        616 (CODE+ICODE+DATA)
Messages      484 (CODE+ICODE+DATA)
RTLConsts     440 (CODE+ICODE+DATA)
Unit1         416 (CODE+ICODE+DATA)
StdActns      396 (CODE+ICODE+DATA)
ActiveX       372 (CODE+ICODE+DATA)
SysInit       308 (CODE+ICODE+DATA)
CommCtrl      280 (CODE+ICODE+DATA)
IniFiles      148 (CODE+ICODE+DATA)
Clipbrd       140 (CODE+ICODE+DATA)
Dwmapi        100 (CODE+ICODE+DATA)
MultiMon       68 (CODE+ICODE+DATA)
WinSpool       40 (CODE+ICODE+DATA)

Delphi 2007

Name        Size Group
--------- ------ -----------------
Controls  79 643 (CODE+ICODE+DATA)
Forms     62 744 (CODE+ICODE+DATA)
Classes   40 223 (CODE+ICODE+DATA)
Menus     31 890 (CODE+ICODE+DATA)
Graphics  31 289 (CODE+ICODE+DATA)
SysUtils  27 153 (CODE+ICODE+DATA)
System    23 850 (CODE+ICODE+DATA)
Variants  10 952 (CODE+ICODE+DATA)
ImgList    5 885 (CODE+ICODE+DATA)
ActnList   4 956 (CODE+ICODE+DATA)
GraphUtil  4 742 (CODE+ICODE+DATA)
HelpIntfs  4 714 (CODE+ICODE+DATA)
Themes     3 046 (CODE+ICODE+DATA)
UxTheme    3 028 (CODE+ICODE+DATA)
Windows    2 885 (CODE+ICODE+DATA)
TypInfo    2 203 (CODE+ICODE+DATA)
VarUtils   2 053 (CODE+ICODE+DATA)
MultiMon   1 921 (CODE+ICODE+DATA)
Dialogs    1 877 (CODE+ICODE+DATA)
Registry   1 493 (CODE+ICODE+DATA)
ExtCtrls     858 (CODE+ICODE+DATA)
FlatSB       797 (CODE+ICODE+DATA)
SysConst     728 (CODE+ICODE+DATA)
Project1     555 (CODE+ICODE+DATA)
Consts       528 (CODE+ICODE+DATA)
DwmApi       412 (CODE+ICODE+DATA)
Contnrs      401 (CODE+ICODE+DATA)
Unit1        374 (CODE+ICODE+DATA)
SyncObjs     362 (CODE+ICODE+DATA)
StdActns     301 (CODE+ICODE+DATA)
SysInit      293 (CODE+ICODE+DATA)
RTLConsts    248 (CODE+ICODE+DATA)
CommCtrl     166 (CODE+ICODE+DATA)
Clipbrd      146 (CODE+ICODE+DATA)
IniFiles     109 (CODE+ICODE+DATA)
Types         88 (CODE+ICODE+DATA)
Printers      70 (CODE+ICODE+DATA)

Delphi 5

Name       Size Group
-------- ------ -----------
Controls 61 316 (CODE+DATA)
Forms    49 623 (CODE+DATA)
Classes  30 227 (CODE+DATA)
Graphics 29 307 (CODE+DATA)
Menus    25 319 (CODE+DATA)
System   20 062 (CODE+DATA)
SysUtils 16 664 (CODE+DATA)
ImgList   5 296 (CODE+DATA)
ActnList  3 624 (CODE+DATA)
Windows   2 572 (CODE+DATA)
MultiMon  1 939 (CODE+DATA)
TypInfo   1 360 (CODE+DATA)
FlatSB      799 (CODE+DATA)
Consts      776 (CODE+DATA)
Dialogs     733 (CODE+DATA)
SysConst    712 (CODE+DATA)
Contnrs     452 (CODE+DATA)
Project2    421 (CODE+DATA)
SysInit     396 (CODE+DATA)
Unit1       396 (CODE+DATA)
StdActns    348 (CODE+DATA)
Commctrl    244 (CODE+DATA)
Clipbrd     148 (CODE+DATA)
Printers     72 (CODE+DATA)
ActiveX      64 (CODE+DATA)
Math         64 (CODE+DATA)
CommDlg      56 (CODE+DATA)
Dlgs         56 (CODE+DATA)
ExtCtrls     56 (CODE+DATA)
Imm          56 (CODE+DATA)
Messages     56 (CODE+DATA)
RegStr       56 (CODE+DATA)
ShellAPI     56 (CODE+DATA)
ShlObj       56 (CODE+DATA)
StdCtrls     56 (CODE+DATA)
UrlMon       56 (CODE+DATA)
WinInet      56 (CODE+DATA)
WinSpool     56 (CODE+DATA)

Tagy: , ,

Praxe

Komentáře

13.1.2011 8:21:44 #

pepak

Problém s "prázdnou aplikací" je v tom, že nijak nereflektuje reálné použití. Ale můžeme využít toho, že v YouTube Downloaderu udržuji paralelně tři interfacy: bez GUI (jen příkazová řádka), VCL (stadardní Delphi) a čisté WinAPI. Ve verzi 0.71 tak dostávám následující velikosti (v pořadí bez GUI, WinAPI, VCL):

- Delphi 5: 562.688 - 635.392 - 1.035.264
- Delphi 2009: 826.368 - 904.704 - 1.526.272

Odečtením od no-GUI verze lze zjistit nárůst pro jednotlivé typy GUI:

- Delphi 5: 72.704 (WinAPI) - 472.576 (VCL)
- Delphi 2009: 78.336 (WinAPI) - 699.904 (VCL)

Z toho je mimochodem vidět, že použití unicode nemusí samo o sobě znamenat nijak podstatný nárůst velikosti, "problém" je konkrétně ve VCL. (Kdyby si někdo chtěl vyzkoušet programování ve WinAPI, tak ze zdrojáku YTD se dá IMHO docela hezky dohledat, jak to funguje. Dal jsem si tam i práci s tím, že jsem založil podkladovou třídu TApiForm, která spoustu věcí řeší sama, takže programátor nemusí sestupovat až na tvrdé jádro smyček zpráv.)

Ještě páč zajímavých postřehů z optimalizace YTD:

- Je vhodné minimalizovat použití virtuálních a dynamických metod. Ze dvou důvodů: Za prvé, každé slovíčko "virtual" nebo "dynamic" už samo o sobě nafoukne výsledný kód o několik bajtů (4 nebo 8) za každého potomka této třídy (tzn. v YTD, kde těch potomků mám 160, to dělá skoro kilobajt za každou metodu, kterou z virtuální převedu na statickou). Za druhé, pokud je metoda statická a není v programu nikde volána, Delphi linker ji do exáče vůbec nezapíše; naprosti tomu dynamické a statické metody se zapisují vždy, ať jsou použité nebo ne.

- Pokud tvoříte stringy podle schématu:
konstanta + konstanta + proměnná + konstanta + konstanta + proměnná + ...
je vhodné konstanty uzávorkovat:
(konstanta + konstanta) + proměnná + (konstanta + konstanta) + proměnná + ...
protože pak je kompilátor sloučí do jednoho stringu, zatímco když je necháte bez závorek, tak sloučí jenom ty úplně vlevo až do výskytu první proměnné a ostatní pak bere jako samostatné stringy, což je za prvé pomalejší (spojuje se víc řetězců) a za druhé delší (protože každý řetězec má v exáči 8-11 bajtů hlavičky [8 b. hlavička, až tři bajty na zarovnání na 32 bitů] - platí pro Delphi 5, pro vyšší verze jsem to nezkoumal).

- Velmi doporučuji nástroj USGParse.exe pro dohledání, které unity jsou používány a odkud. Velmi pravděpodobně zjistíte překvapivé závislosti, které dramaticky prodlouží váš program (když třeba použijete unitu FileCtrl, protože z ní chcete použít proceduru ForceDirectories, tak se vám do programu taky narve Forms a jí použité třídy, takže program najednou naroste o 300 KB. Je lepší si tu ForceDirectories vytáhnout extra nebo si ji rovnou napsat sám.)

pepak

13.1.2011 10:40:33 #

radekc

To je právě problém Delphi 5. Myslím, že už v Delphi 6 v souvislosti Kylixem došlo k velké perestrojce ohledně závislostí a řešící např. i tvůj problém ohledně ForceDirectories. V FileCtrl sice zůstala procedura ForceDirectories, ale ta vola SysUtils.ForceDirectories(Dir).

Jinak díky za komentář, některé věci jsou zajímavé, i když moc nevěřím tomu s tím uzávorkováním řetězců, že to ještě platí.

A poslední věc: programovat čistě ve WinApi je podle mne "nerozvážnost" a do budoucna to přinese více problémů jak užitku i s ohledem na portaci na 64bit nebo jiné OS a to si nedovedu představit už jen problémy s kompatibilitou současných OS Windows. Možná tak ještě pro aplikace typu Hello world.

radekc

13.1.2011 11:06:31 #

tomk

Zajimava poznamka o ForceDirectories. Nastesti ForceDirectories je v SysUtils a funkce ve FileCtrl ji vola (to je skoro jako dvoji zdaneni).

tomk

13.1.2011 11:06:32 #

radekc

No a ještě si uvědomuji, že vyšší verze zavádějí podpory pro XP themes a vyšší Windows a samozřejmě to se projevuje také na velikosti programu.

radekc

13.1.2011 11:09:41 #

radekc

Jo, ale až pravděpodobně od verze Delphi 6, která řešila i další podobné závislosti. A ta duplicita je pravě k vůli kompatibilitě s staršími verzemi.

Nyní si autoři Delphi dávají velký bacha na závislosti - viz komentáře v SysUtils atd.

radekc

13.1.2011 11:38:33 #

pepak

Ad 1: Ale jo, jasně. Chtěl jsem upozornit ne na konkrétní příklad FileCtrl, ale na obecný problém, který se vyskytuje - buď přímo v RTL/VCL, nebo v kódech cizích komponent. Pokud záleží na velikosti, stojí za to se podívat, které unity se používají a odkud, protože často vyplynou úplně nesmyslné věci (komponenta používá forms, protože cestu k exáči čte přes Application.ExeName a ne přes nezávislé ParamStr(0) apod.).

Ad 3: Není to tak černobílé. Portace na jiný OS je samozřejmě při použití WinAPI problém (portace na 64bit už ne nezbytně), ale má i své výhody - například to, že program v Delphi jde bez problémů zkompilovat FreePascalem (a obráceně), což u VCL aplikace zdaleka neplatí. Plus je tu ta velikost, samozřejmě. Nebo to, že mohu celkem jednoduše napsat aplikaci fungující i pod Windows 98, která nicméně dokáže využít specifických featur pozdějších operačních systémů. Jsem dalek toho, abych každému doporučoval zahodit VCL a programovat jedině ve WinAPI, ale jsou případy, kdy to stojí za zvážení.

pepak

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ů