views:

1486

answers:

16

I'm working on a large delphi 6 project with quite a lot of dependancies. It takes several minutes to compile the whole project. The recompilation after a few changes is sometimes much more longer so that it is quicker to terminate Delphi, erase all dcu files and recompile everything.

Does anyone know a way to identify, what makes the compiler slower and slower? Any tips how to organize the code to improve compiler performance?

I have already tried following things:

  • Explicitly include most of the units in the dpr instead of relying on the search path: It didn't improve anything.
  • Use the command line compiler dcc32: it isn't faster.
  • Try to see what the compiler does (using ProcessExplorer from SysInternals): apparently it runs most of the time a function called 'KibitzGetOverloads'. But I can't do anything with this information...

EDIT, Summary of the answers until now:

The answer that worked best in my case:

  • The function "Clean unused units references" from cnpack. It almost automatically cleaned more than 1000 references, making a "cold" compilation about twice faster. ("cold" compilation = erase all dcu files before compiling). It gets the reference list from the compiler. So if you have some {$IFDEF } check that all your configurations still compile.

The next thing I would like to try:

  • Refactoring the unit references manually (eventually using an abstract class) but it is much more work, since I first need to identify where the problems are. Some tools that might help:
    • GExperts adds a project dependencies browser to the delphi IDE (but unfortunately it can not show the size of each branch)
    • Delphi Unit Dependency Viewer V1.0 do about the same thing but without Delphi. It can calculate some simple statistics (Which units is the most referenced, ...)
    • Icarus which is referenced on a link in one of the answer.

Things that didn't change anything in my case:

  • Putting every files from my program and all components in one folder without subfolders.
  • Defragmenting the disk (I tried with a ramdisk)
  • Using a ramdisk for the code source and output folders.
  • Turning off the live scanning antivirus
  • Listing all the units in the dpr file instead of relying on the search path.
  • Using the command line compiler dcc32 or ecc32.

Things that didn't apply to my case:

  • Avoiding having dependencies on network shares.
  • Using DelphiSpeedUp, because I already had it.
  • Using a single folder for all dcu (I always do it)

Things that I didn't try:

  • Upgrading to another Delphi version.
  • Using dcc32speed.exe
  • Using a solid-state drive (I didn't tried it, but I tried with a ramdisk where I put all the source code. But maybe I should have installed delphi on the ramdisk too)
+7  A: 

Things that could slow down the compiler

  • Many unused units in your uses clause. See this question for a link to cnpack.
  • Not explicitily adding units to your project file. You've already seem to have covered that.
  • Changed compiler settings, most notably include TDD32 info.

Try to get rid of unused units in your uses clause and see if it makes a difference.

Lieven
Thanks for your answer. cnpack seems interesting. I will have a try. Include TDD32 is already deactivated.BTW there is also a compiler called ecc32 (which calls dcc32), I don't know the exact difference.
Name
@Name, I didn't know that, sorry for the edit. Now you mention it, there's also dcc32speed.exe. It's written by Andreas Hausladen and patches several functions to speed up the compiler.
Lieven
The function "Clean unused units references" from cnpack was a very good answer. It almost automatically cleaned more than 1000 references, making a "cold" compilation was about twice faster.
Name
+7  A: 

Check are there any paths in search paths that aren't on your local machine.

i.e. Don't link to binaries on network shares, and check that the search path isn't checking any network shares.

Binary Worrier
Nothing is on a network shares. But a good tip anyway.
Name
+4  A: 

I haven't seen the compiler get slower over time, but it's been a long time since we used Delphi 6.

  1. It seems to be generally agreed upon in the Delphi community that, if you don't want to upgrade to the latest and greatest (Delphi 2007 or 2009), then Delphi 7 is the best/fastest/most stable. You might consider upgrading.
  2. KibitzGetOverloads sounds like something from the kibitz compiler -- the "background" compiler that gives you code-completion, background error highlighting, code tooltips, etc. Sounds like you'd be better off checking the call stack of the command-line compiler, not the IDE; you'd get something more helpful.
  3. I have never found compiles to be faster after deleting the DCUs. DCUs are there to make the build incremental, therefore faster. If you're seeing faster compiles after deleting all DCUs, check your hardware. Have you defragged your hard disk lately? How much free space do you have on the drive?
Joe White
Same thing for the command-line compiler, it apparently spend a lot of time in KibitzGetOverloads. Disk space is not a problem defragmenting probably won't help, as I get the same result when I put the whole source code on a ramdisk. Upgrading to a newer Delphi might be an option, but I would prefer to find out, what makes Delphi slow.
Name
+3  A: 

Although only partly relevant to your exact question, I hear that the use of a solid-state drive is vastly increasing compile time with Delphi - Nick Hodges said this himself on the Delphi Podcast a couple of week ago. Brian

Brian Frost
Interesting Idea, which gave me another Idea: I tried to put the whole source code on a ramdisk. But I did'nt get any improvement. Windows probably caches the files good enough.
Name
+4  A: 

You could give DelphiSpeedUp a try and see if it makes a difference. It won't speed commandline compiles up, but it claims to have some speedups for the IDE compile.

Lars Truijens
I already have DelphiSpeedUp. Thanks for the tip anyway.
Name
+7  A: 

Hi, using Delphi 7 and 2009, last week I pass from almost 2 minutes for compiling and another 45 seconds from hitting f9 and get the main form of my app to 20 seconds compiling and running. This things has drive me crazy for about 6 months and nothing I tried seems to work. Using filemon from SysInternals, I realize than every unit (mostly components) that compiler requires was searched in every folder that was in Search Path, yes, this produce a LOT of FileOpen, FileExists and FileNotFound, etc. What I do was, put every DCU, DFM, RES, etc from components all in a single folder, and having just this folder in the search path, and a couple of others folders required by the project; the results were amazing. Other problem prior to the fix, was debugging. It takes almos 40 seconds in each F7, F8 key press while debuging, this has been fixed too. Hope this info can help you. Greetings form Isla de Margarita, Venezuela. Excuse my english, if any error ;)

José Romero
Not very practical but it might be worth a try.
Name
I tried it, it did'nt change anything in my case.
Name
+3  A: 
  1. Have you set a single folder to get the DCUs. If not, they will be scattered all over.
  2. Put all the units and their implicitly called units (except installed components from Library path) in the dpr. To be sure you did not miss some, empty your search path, it still should compile.
  3. After reducing the search path, you can try to reduce your library path by installing your components into fewer folders.
François
I do number 1 systematically, but it might be a good tip for people who don't do it. I alreay tried number 2 as already said in my original post. I don't know if number 3 would help, but it would be quite a lot of work to apply, so it would be the last hing I might try.
Name
+1  A: 

Try to install a ram disk and set your dcu output path to point there. This more than halved my compilation time with Delphi 2007 on top of DelphiSpeedUp.

dummzeuch
I have already tried that after Brian Frost told the solid state drive seems to increase performance. In my case it didn't change anything. May be Windows already does a good job at caching the files.
Name
+2  A: 
AhmetC
I wouldn't know where to divide the code source at the right place to improve compiling time in most cases because I don't know what makes the compiler slower. So it might last long until I really get good results. +1 for the tip about the antivirus. I didn't thought about that until now, it is worth a try.
Name
The third point can be alleviated if the AV allows path exceptions, so you can list there <BDS>\Lib; <project>\dcu; <components> etc. So it will not hard the compilation times. I know that avast! have this option on home edition. Don't know others
Fabricio Araujo
+1  A: 

The compiler will only compile units that have changed. If you have changed the code in the interface section all units that depend on the changed unit are compiled. If only code in the implementation section is changed, the compile will only that unit but presumably link all the modules. Implies a good design of interfaces up front but if you restructure the code to restrict changes to the implementation compile times might reduce. I have no idea by how much. This fact is mentioned in the Delphi help files under Multiple and indirect unit references in Delphi 7 "Using Delphi".

I would like to refactor the code to improve compiler speed. But I wouldn't know where to start. IT would be nice to have a tool that shows which dependencies cause problems. But such a tool probably doesn't exists
Name
+2  A: 

Hello.

We had the same (or similar) problem. I of our package has compilation Time about 12 min. After changes, now we have moved to 32 sg.

After many tests we found that the "problematic situation" was the following: In a single package:

  • The A unit uses a large number of units: U1, U2, U3, U4, ... U100 (Uses of Interface) in the same package. This is an important unit that centralizes all the initialization work.

  • All units of the package, U1, U2, U3, .., U100 uses unit A (use of implementation)

This "circular reference" does not give compilation errors because the USES are different, but caused a large compile-time.

SOLUTION: Eliminate the reference to each unit, U1, U2, U3 ,...., U100 in the A Unit.

Now, A unit use a large number of units: U1, U2 ,...., U100, but the units U1, U2 ,..., U100, does not use the unit A.

After this change the compile-time is down drastically.

If you have a similar situation, you can try this.

Excuse for my bad english.

Greetings.


Neftalí -Germán Estévez-

Neftalí
Interesting observation. I think I have such a case. I will try to have a look.
Name
See also the link given by Fabricio Araujo, which goes in the same direction: http://coding.derkeiler.com/Archive/Delphi/borland.public.delphi.non-technical/2006-05/msg00700.html
Name
+1  A: 

I had the same problem and I can come up with (2) reasons it effected me.

  1. Circular references. The gentleman who stated that one was correct. I would have certain LARGE projects that would compile fast, and SMALL projects that compiled slow. Could not figure it out until I restructured the code and then I got the faster compile speeds. Lots of small units. It's easy to build monolithic units. But, there are many penalties from it.

  2. I've heard it a 1000 times, develop on a slow machine like your users might be using. Hey, that's for the testing department. I can't waste time with compiling, Delphi load speeds, packages, etc. I went out and bought a "GAMERS" computer (WOW) with the Solid State Drives (as mentioned earlier), 12GB RAM, OVERCLOCKED "i7" Intel chip, triple video cards (linked), all on Vista64 (Vista is not bad once it is finally running with all installed parts). It was a real pain to get it all set up. But, I am not waiting anymore on my computer. Pure compile speed, load speed, plus a new fresh machine without all of the crap that was installed on the last one over the last 2 years. I even unloaded DelphiSpeedUp. Did not need it. And I don't need to turn off AntiVirus, since I did that one as well, and got penalized with the internet crap. So AntiVirus stays on. Pure and simple, get a BALLS OUT machine. Your time is worth more than what you will spend on a new computer.

Why stop at 12 GByte, wouldn't 32 be much more BALLS OUT? No seriously, could you add some information why anyone would need this ridiculously over-the-top machine to do *Delphi* development?
mghie
He has asked how to increase compiler speed. Since when SLI/Crossfire/Solid state disk increase Delphi compiling speed? Since when Delphi requires more than 2GB ram?
Ertugrul Tamer Kara
VM caches in available RAM, so your source files end up getting cached in RAM if you have lots of it. Also, solid state disks have lower random access times, so files are found and read faster. Disk is the bottleneck during compile, so anything that speeds up disk speeds up compile times.
Joeri Sebrechts
+1  A: 

See this.

I tested it with a VCL.NET codebase and worked.... Don't know if it remain valid for D2009, but it's worked on D2006.net

Fabricio Araujo
It goes in the same direction as the answer of Neftalí but with one improvment: the suggestion with the abstract class to improve performance. Thanks for the completment.
Name
A: 
  • Do not compile on network drives. Seek time is dramatically worse.
  • Consider pointing your dcu ("unit output" directory to a ramdrive.
  • Limit the number of include/unit directories.
  • Try to avoid minor circular references that the compiler still accepts, specially for large units (e.g. generated ORM units for your OPF). It might cause large units to be compiled twice. (does Delphi allow minor mutual circulars, or is that a FPC only feature?)

I never tried, but hardcoding all files with full/relative path in the central .dpr might also help (script to regenerate/update?). (you mention that above, but was it with path xx in '\path\yyy' notation?).

Other long shots:

  • Use Kylix (file/dir I/O under Linux is dramatically better in my experience (though that is from FPC experience)). Maybe we need a reversed cross-kylix :-)
  • Use a separate (windows) build machine, and tweak NTFS over the registry to be less "safe". (which you don't care for, since everything is a revision system to begin with). Afaik these options can only be done global for all filesystems, hence the separate system. Throw in a raid array or Raptor too.
  • Forget solid state. Nice buzz atm, but the high write ratio will kill it eventually (both life and performance when it gets fuller and can't optimally allocate anymore), and you need the expensive intel ones to beat two $75 HD's in RAID.

P.s. Sorry for the FPC references. I do both, and I sometimes don't know anymore what belongs to what.

Marco van de Voort
"minor mutual circulars"? Since I never heard about it, I believe that is a FPC-only feature.
Fabricio Araujo
A: 

Since I have not racked up 50 reputation points I cannot respond to my BALLS OUT post. So I have to start a new line item here. I bought the machine to work on very large Photoshop files, and I also do a lot of 3D modeling in Inventor and 3DStudio MAX. That's why I bought the new machine. BUT... I have definately receive a tremendous boost in my Delphi usage because of it. My salary costs way more than the extra 2K I spent on the new machine as opposed to purchasing some basic Dell (which may be fine for Delphi). So any BOOST I may receive is a BONUS. If you do this job all day, every day like I do, any latency you experience starts to become real a problem. Which it did for me with using Photoshop, Autodesk products, and DELPHI. So I will say it again, a new BALLS OUT machine, WILL improve your performance. The guy was asking what can he do to improve compiling performance. So, I gave my opinion.

P.S. Put Delphi and your project on a Solid State Drive, and you will see a BIG speed improvement.

A: 

What I do is always make sure to have very few directories in the library path, and most of the components and static code. I also make sure that NO sourcecode is available in the library path, only .dcu/.res etc. Only browsepath has the sourcecode, and special circumstances are handled through searchpath for the project.

Just limit what you compile in any situation.

Atle