What Can I Do To Reduce My Executable's Size (Delphi)?

26,069

Solution 1

When moving from Delphi 7 to Delphi 2010., our .exe's grew for example from 16 megs to 35 megs.

I asked a question similar to yours on the Embarcadero forum a few weeks ago. (link) In my OP, I listed a series of links on this subject that you might find helpful.

We tried using UPX to compress our .exe's. Letting it work for hours significantly reduced our .exe, but we probably won't use it in production for these reasons:

  1. We have quite a few .exe's and don't want to wait 1/2-day on each build. (It's possible that we could find a non-brute force set of parameters to UPX that would reduce this...)

  2. Although the size of the .exe is reduced, our shippable was not, because our installer (not surprisingly) is unable squeeze much more compression out of the already compressed file... whereas it was able to reduce the original 16 meg .exe down to 8 megs.

  3. I've read some reports that at some time (rarely, but not never), UPX exe's triggered various anti-virus programs to report the application contained a virus. (I don't recall the date, site, or details of where I saw this, so it's a bit unfair of me to report it here.) But, we are so adverse to taking a risk of that even possibility happening, that UPX is off the table...

The link on the Embarcadero forum also includes a link to another SO thread on this topic.

I continue to be surprised and disappointed at the code bloat we found when moving to Delphi 2010. As Nick notes, 2X for Unicode is quite excessive.

However, the bloat is a relatively minor trade-off when moving to D2010, because, IMO, D2010 is such a terrific upgrade in so many other ways. But, it does mean that we'll probably have to move to shipping 2 CDs rather than one. I'm not looking forward to seeing the reaction to this from our organization...

Solution 2

Without seeing the actual settings that your "Release" build configuration uses explaining this increase in size requires a great deal of speculation.

Beyond some perhaps unlikely factors resulting in a vast increase in the amount of code being "dragged in" even though it isn't used, that magnitude of increase would most easily be explained by the inclusion of debug information.

I would check your compiler and linker settings for:

  • Debug Information (compiler setting)
  • TD32 info (linker)
  • Remote debug info (linker)

Compare these settings in your Delphi 2009 project with the equivalents in Delphi 4.

Solution 3

Factor out the expected 2X increase from Unicode and you end up with a 2.5X increase unaccounted for. This makes sense considering how many versions you've skipped. A lot's been added to the VCL and RTL since Delphi 4, and not all of it is stuff that can be easily smartlinked out, even if you never use it. Depending on how many units you're using, you could be hauling in quite a bit of extra baggage.

Allen Bauer and the compiler team added a new feature into D2010 to help reduce this, but apparently they're treading cautiously and didn't use it in as many places as they could have. Hopefully we'll see more cruft reduction in 2011 and subsequent releases.

Solution 4

I will add my few words. Linker can remove unused procedures and functions only if it can follow the code hierarchy. The nightmare list for linker listed below:

  • Message-driven code, the sad news is that this code can't be removed whatsoever, that's why Delphi blank project size continues growing from version to version. Every new windows message (WM_TOUCH for example as long as I know introduced recently) creates procedure call hierarchy that can't be removed (even if you don't have plan to use Touch API at all). This is because every case WM_: fragment is something linker can't decide whether it will be used or not.

  • Code and data structures accessed from the begin end, initialization, finalization secions of the units. Here you have some control, remove unnecessary calls or object creation. Even if you create objects on demand and only free them in finalization section, make it carefully

Solution 5

Use "upx - compress or expand executable files" @ http://upx.sourceforge.net


If you go to tools/configure tools, and set it up like this, you can compress the executable that you're working on easily via a menu item in the IDE.

Configuration

Share:
26,069

Related videos on Youtube

lkessler
Author by

lkessler

I'm a Programmer and a Genealogist. I am the developer of the Genealogy Software: Behold Also the DNA Analysis Software: Double Match Triangulator I operate the GenSoftReviews site My blog | My Tweets | Brute Force If you're into Genealogy, I recommend you try the Genealogy and Family History Stack Exchange site at: http://genealogy.stackexchange.com/ See My Family Research and Unsolved Mysteries

Updated on July 09, 2022

Comments

  • lkessler
    lkessler almost 2 years

    I release a single executable (.EXE) for a desktop program using Delphi 2009. I have no external DLLs or resources that I need for the program to run.

    I use two components: LMD Innovative's ELPack and Sergey Tkachenko's TRichView that are compiled into my executable.

    When I build my production version, using the "Release" build configuration, the executable file produced is 13,533 KB.

    Prior to using Delphi 2009, I was using Delphi 4. The executable it produced was only 2,671 KB while incorporating the same two components and basically having the same code as my current version.

    I do understand that Delphi 2009 is completely Unicode (which is the main reason why I upgraded), and being Unicode can cause up to a doubling of size. But this is about 5 times larger.

    Is there a reason why my executable has to remain 5 times larger? Or are there some simple ways to cut down a significant chunk of the executable size?


    Please note. Some people are answering with ways to compress the Delphi EXE. That is not what I am trying to do. I am trying to simply see why so much space is being used to remove what might not be necessary. If that is done, compression can still be done afterwards if so desired.

    It really doesn't matter how big or small the executable is once it is installed. It is for downloading purposes and to minimize server load and download times that you want to compress it. I prefer to use Inno Setup and compress the program inside the install routine itself. Then when it is installed, it is expanded to full size. That both prevents possible detection as a virus and eliminates the extra startup time needed to uncompress the program in memory. Also I code sign both my executable and my install routine and some compression techniques are incompatible with that.

    For more info about compressing, see the StackOverflow question: Delphi EXE compressor?


    ldsandon asked me to provide exactly what options I'm using, so here they are:

    Compiling Options
    (source: beholdgenealogy.com)

    Linking Options
    (source: beholdgenealogy.com)

    • Admin
      Admin almost 14 years
      Which compiler switch are you currently using? Those impacting code size most are those adding debug information or control code to the project.
    • lkessler
      lkessler almost 14 years
      @splash: I have about 400 KB of my own code in about 20 units. They include 14 forms that use about 500 KB for the dfm files. That does not include the code in two components I use.
    • lkessler
      lkessler almost 14 years
      @ldsandon: I think I'm using all the defaults for the "Release" build configuration.
    • Admin
      Admin almost 14 years
      I no longer know what the defaults are because those out of the box are not "correct" and I changed them and made another default. IIRC they have optimization enabled, but add some debug info anyway, have string format checking on, and so on. It would be useful to know what options you're using actually.
    • arthurprs
      arthurprs over 13 years
      Try DebugDCUs = OFF, Map File = OFF
  • Mason Wheeler
    Mason Wheeler almost 14 years
    I know. It's a fair bit less than that, since not everything in the app is a string. But my main point is that a lot of it comes from the standard libraries getting bigger.
  • lkessler
    lkessler almost 14 years
    Thanks @Deltics: I believe I am using all the default Delphi 2009 "Release" settings. In Delphi 2009, the TD32 setting has been replaced by Linking Debug Information (see: blogs.embarcadero.com/chrishesik/2009/09/15/34920 ) which I have as "False". Remote debug symbols in the linker is False. But I do have Compiling Debug Information as True, Debugging Symbols as True and Local Symbols strangely in opposition to them as False. Then there's Linker output as Generate DCUs and Map File as Detailed. I can play with those, but I'll be surprised if they save me very much.
  • lkessler
    lkessler almost 14 years
    My next major upgrade will be for either 64 bit or Cross-Platform compilation, whichever comes first. I hope my executable doesn't grow to 30 MB then.
  • Deltics
    Deltics almost 14 years
    You may be surprised at how much difference Debug Information can make. At the very least it would be worth turning it off and finding out. Also, are you using MadExcept or any similar utility which may be embedding the MAP file in your executable in a post-build step?
  • Marco van de Voort
    Marco van de Voort almost 14 years
    64-bit really is bulkier than the same x86. But for code only, and the question is if this is all code. As Mason said, to answer that we would have to find what causes the (at least) 2.5X factor that is unaccounted for
  • lkessler
    lkessler almost 14 years
    @Tom1952: You cannot compress something twice. So it is better to use the installer to do the compression to reduce download size. I use InnoSetup and it includes my 13.5 MB program into a Setup package that is only 4.5 MB. When the setup is run, it decompresses the program to its full size, so it will not have any possible virus detection problems.
  • lkessler
    lkessler almost 14 years
    @Tom1952: Thank you for the link to your similar question on the Embarcadero Forums. That's a very interesting discussion (including some comments by Peter Below). One point you mentioned is about large icons. Well, I did add some large Vista icons to my program that could have added a MB to the size. Maybe the program you wrote might help me.
  • lkessler
    lkessler almost 14 years
    @Tom1952: I hadn't seen that other SO question. That's a good one with good ideas and links to a few useful utilities.
  • lkessler
    lkessler almost 14 years
    @Deltics: I do use EurekaLog for tracing errors, but I have most of its options (including memory leaks) turned off. Turning off EurekaLog entirely only reduces the executable by 90 KB.
  • Marco van de Voort
    Marco van de Voort almost 14 years
    D2010 is a different matter due to its expanded RTTI possibiltiies, I can imagine that a wrong management of that (turning it on everywhere) can bloat an exe. OP was talking about D2009.
  • Cosmin Prund
    Cosmin Prund almost 14 years
    @lkssler, EurekaLog has the odd habit of turning on Debug Info for your exe if enabled. Did you try disabling EurekaLog, then turning off all "debug" options in the build configuration and then building again? 90Kb is not enough decrease in size for removing debug information. I gave up on EurekaLog because it messed with my build configurations, never looked back.
  • Chris Thornton
    Chris Thornton almost 14 years
    UPX triggering false-positive is a risk, certainly. But you can also get the same with your setup, any library, or by using any particular development environment (Delphi, VS, etc..). So while you can't elmiinate the risk, it is reasonable to cut down on the number of risk factors by skipping UPX.
  • Chris Thornton
    Chris Thornton almost 14 years
    IMO, you're better off leaving the UPX for later in the deployment process. i.e. don't bother with it in the IDE, it just slows you down. Wait until you're ready to deploy, and do it in the same job (.bat file, Visual Build Pro, etc..) that you codesign, localize, build the setup, etc..
  • lkessler
    lkessler almost 14 years
    Thanks @Cosmin, I'll look into that.
  • philnext
    philnext almost 14 years
    But you can use StripReloc AND a compressor.
  • lkessler
    lkessler almost 14 years
    I'm asking the question not to simply reduce the size of the executable, but to identify any useless excess size and find why it grew so much between Delphi versions. To reduce download time, I use InnoSetup to create a compressed setup file. See my comment to Tom1952's answer.
  • lkessler
    lkessler almost 14 years
    Thans @philnext. Unfortunately, I didn't reinstall Delphi 4 when I went to a new machine. I need old versions of ElPack and TRichView to work with it and I remember they were a bugger to install back then, so it was never worth the bother, especially since my new code is Unicode and completely incompatible with Delphi 4 now.
  • lkessler
    lkessler almost 14 years
    See my comment to Adam's answer.
  • lkessler
    lkessler almost 14 years
    @Tom1952: Code Bloat: Well from 16 MB to 35 MB isn't as bad as the exponential growth of Microsoft's Operating Systems over the years.
  • Cosmin Prund
    Cosmin Prund almost 14 years
    Looking at your compiler options, why are you linking debug dcus?? Those are larger, might prevent the linker from removing unused code, might be slower.
  • lkessler
    lkessler almost 14 years
    @Cosmin: Not sure what you mean by saying I'm "linking debug dcus". In my linking configuration, Debug information is "False" and Linker output is "Generate DCUs". You can't turn off "Generate DCUs" unless you generate C++ objects instead, which I don't want to do.
  • Cosmin Prund
    Cosmin Prund almost 14 years
    @Lkssler, on your "Delphi compiler/Compiling" image, look at the focused line, the one with the double black arrows in front of it, it's the 5th line under "Debugging". It reads: "Use debug .dcus" and it's True. You've also got "Debug Information" = True, this is the 2nd line under "Debugging", make it False. Build with those settings flipped and report back, I'm curious.
  • mjn
    mjn almost 14 years
    @lkessler how can I see if something grows exponentially if I have only two samples (16 and 35)? :)
  • lkessler
    lkessler almost 14 years
    @Tom1952: You can add my 2.5 MB Delphi 4 to 13.5 MB Delphi 2009 and now you have four samples. :-)
  • Alex
    Alex almost 14 years
    @Cosmin Debug information is NOT included into executables. So, "debug information" and "Use Debug DCUs" options do not affect executable. These options only affects DCU files. Of course, enabling EurekaLog will mean including debug information, but it's a very tiny overload, as lkessler already pointed out. Turning off EurekaLog will turn off adding debug info - so no matter what your options are - debug info will not make it into executable.
  • VibeeshanRC
    VibeeshanRC over 13 years
    yes , everyone know exe compressor can compress exe , and ASpacks is a good compressor , but this is not a question discussing which is the best compressor
  • VibeeshanRC
    VibeeshanRC over 13 years
    stripreloc is good (because it is not compressor ) but it cant reduce the size
  • David Heffernan
    David Heffernan over 13 years
    StripReloc does reduce the size of the exe, by a small amount, but you can do the same with {$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED}
  • 0xC0000022L
    0xC0000022L over 12 years
    What about a "smart linker" that watched to much TV in all those years and got dumb? ;) ... the smart linker does not throw out a lot of unneeded stuff, despite its uselessness in the resulting binary, ergo it isn't as smart as its creators like to think of it.
  • Tuncay Göncüoğlu
    Tuncay Göncüoğlu over 9 years
    This actually is a very good way to hunt down those pesky 16k PNG images that sneak into the form as 3MB bitmaps.