The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,858 other subscribers

Delphi: Optimizing extremely long compile times

Posted by jpluimers on 2010/08/26

Anthony Frazier mentions two very true paths for optimizing your Delphi compile times:

  1. Avoid units with the “read-only” attribute set.
  2. Avoid large circular dependency groups, particularly if you put everything in the interface’s uses clause rather than the implementation uses clause.

To get rid of the second, you should split your interface and your implementation.
Often, one of these two solutions work for that well:

  • Create the interface as a base class, then implement it in a descendant.
  • Create the interface as a Delphi interface, then implement it in a class.

Only if those options do not work, then start using Delphi SpeedUp by Andreas Hausladen.

–jeroen

Via: TPersistent.com » Blog Archive » The Power of Open Source.

19 Responses to “Delphi: Optimizing extremely long compile times”

  1. Xepol's avatar

    Xepol said

    “Avoid large circular dependency groups, particularly if you put everything in the interface’s uses clause rather than the implementation uses clause”

    You can’t create circular dependancies without using the implementation uses clause. Circular dependacies at the interface level will not compile under any conditions.

    • Yeah, I suppose a “does not compile at all” situation could be considered INFINITE compilation time, so removing circular unit references reduces INFINITE to FINITE, which is undeniably an impressive optimization. LOL

    • jpluimers's avatar

      jpluimers said

      Actually, I was talking about ‘groups’.
      Having unit A using unit B and unit C in the interface, where B and C are in cycles can in fact make compiler performance worse than having B and C used in the implementation of A.

      Does that make my point more clear?
      –jeroen

  2. Pete R.'s avatar

    Pete R. said

    You said:

    * Create the interface as a base class, then implement it in a descendant.
    * Create the interface as a Delphi interface, then implement it in a class.

    This does not make sense. “Create the [unit] interface as a base class.” The unit interface can only be created as the unit interface. Units may contain classes (or they may not). Units are not classes. This is like saying “create the egg as an egg carton.”

    “[T]hen implement it in a descendant.” Except for abstract methods, a base class must be implemented. You can’t skip implementing it simply by creating descendant classes.

    “Create the [unit] interface as a Delphi interface.” Same problem. See above.

    “[T]hen implement it in a class.” If by “it” you mean interfaces descended from IUnknown then of course you would implement it in a class. There is no other way to implement an interface. If by “it” you mean unit interfaces then, again, unit interfaces can only be implemented in . . . unit interfaces, of course.

    Please don’t construe my comments as a personal attack. I hope my response leads to greater understanding and not hurt feelings (as sometimes unfortunately happens).

    • jpluimers's avatar

      jpluimers said

      I was trying to refer to ‘interface’ interfaces and ‘class’ interfaces, not ‘unit’ interfaces and the implementation using classes.
      Class interfaces can be either using abstract methods, or contain empty method implementations. Neither these two need extra units in the implementation uses lists.

      The reason for limiting it to that, is that large unit uses cycles are usually not caused by other things (like global procedures, or value types).

      So thanks for pointing at the ambiguity; I hope my reaction makes it more clear now.

      –jeroen

  3. Patrick McGovern's avatar

    Patrick McGovern said

    Hello! I don’t understand this statement:

    “Only if those options do not work, then start using Delphi SpeedUp by Andreas Hausladen.”

    I’ve found that SpeedUp is a great tool to have installed. I don’t have huge programs, but lots of medium sized ones. SpeedUp simply makes the IDE much more responsive. So my thought is, “So why not use it?”

  4. IL's avatar

    IL said

    What’s wrong with unit’s read-only attribute set? Did you mean source .pas files or compiled .dcu?
    By the way, Jedi VCS sets read-only for files that were checked-in.

    • jpluimers's avatar

      jpluimers said

      It was with read-only source files.

      I’m not sure what is wrong; I’ve just seen that behaviour happen a few times in the past (I think it was pre 2007, but I’m not sure).
      I have not seen it in Delphi 2010.

      Since this post was meant as a general guideline for any Delphi version, I think it is important to address the read-only aspect as well.

      –jeroen

      • Andreas Hausladen's avatar

        Andreas Hausladen said

        Older Delphi versions (pre 2007) open files in read/write mode. If the file is read-only an exception is raised by TFileStream.Create. This exception is caught and the file is opened in read-only mode. This alone slows down the file-open function because exceptions cost many CPU cycles. And with the introduction of Quality-Insight (the call stack) this got even worse because the CPU cycles for exception exploded.

  5. Andreas Hausladen's avatar

    Andreas Hausladen said

    > Only if those options do not work, then start using Delphi SpeedUp

    Interesting logic. Fortunately I do not have such a logic ;-)

    • jpluimers's avatar

      jpluimers said

      My point is that you should first narrow down the problem to something that can be fixed within the out-of-the-box Delphi install before resorting to other means.

      In my experience, adding Delphi SpeedUp after solving the original issue, improves it even more!

      –jeroen

      • Andreas Hausladen's avatar

        Andreas Hausladen said

        > improves it even more

        DelphiSpeedUp mainly optimizes the IDE and the compiler’s interaction with the IDE. It doesn’t optimize the compiler’s algorithms. That what your “avoid large circular dependency groups” does.

      • IL's avatar

        IL said

        Thanks for recap! DelphiSpeedUp has a great use for my daily work on D7 mostly.

  6. Fritz Franz's avatar

    Fritz Franz said

    My problem is that sometimes delphi turns to compile my project within 15 minutes. Normally it takes less then 30 seconds. When it takes that long the hard drive is fully engaged. Closing some applications sometimes helps.
    My system is Win XP Pro (newest patch level) with 3 GB RAM.
    I don’t think this issue can be resolved by your suggestions.
    Anyway thanks for your effort!
    Regards, Fritz

    • jpluimers's avatar

      jpluimers said

      How much memory is Delphi using when the compile time increases to that much?

      –jeroen

    • Alistair Ward's avatar

      Alistair Ward said

      hi,

      Our project recently blew out to about 45 minutes build time (~2000 units, 1.3million lines). I reduced this back to 3 minutes by refactoring 3 critical units.

      The critical units were all basically “container” units that held objects of many classes, and were in turn referenced by the implementation uses clauses of many other units.

      More concrete:

      I had a TProject in project.pas

      I changed this to a TProjectImplementation in ProjectImplementation.pas, and project.pas became:

      unit Project;

      interface

      uses
      ProjectImplementation;

      type
      TProject = class( TProjectImplementation )
      end;
      initialization
      end.

      This is the reverse of the suggestion (1) above, but is really easy to do and can be done without affecting other units.

Leave a reply to Fritz Franz Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.