Re: VS .NET 2003 hangs while "Generating Code..."

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Joseph M. Newcomer (newcomer_at_flounder.com)
Date: 11/01/04


Date: Mon, 01 Nov 2004 04:26:33 -0500

Well, it certainly smells like a serious compiler bug.

If you are doing these as 11,000 "Add" methods, just one line after the other, for example
as
      data.Add(_T("string1"), _T("string2"), _T("string3"), _T("string4"), _T("string5"));

then you have taken a truly inefficient approach. Instead, create a const table and write
a simple for-loop to iterate over it and create the dynamic entries. Or load the data from
a resource segment. Generating code to do this is not a healthy approach to the problem.

In fact you probably get horrendous performance at runtime by using CArray::Add. I'd
suggest that if you know how many objects you need to create and instead of doing an Add,
simply do a SetSize once and just use SetAt(); if you don't know the number of elements
but have an idea how large it might be, after creating it do a SetSize(0, n) where n is
the number of elements to add when it expands; for example, SetSize(0, 5000) means that
you will only get three reallocations for 11000 elements. If you think that the extra 4K
is going to matter in the slightest, you could call the FreeExtra method after filling the
array. But that's a runtime issue, not a compile-time issue.

Also, if you don't really know how many elements you need, it is sometimes more efficient
to create the original information as a CList, and only after you've created all the
elements do you put them in an array, and you know how many elements you need in the
array.

If you had to "break down" the task into six functions to avoid compiler limits, you
probably have a more serious problem, which is you probably should have broken it down to
20 or 30 functions. I have never exceeded the capacity of VS6 to compile a program, so the
functions were clearly far too large to start with. Large functions are difficult to
optiimize; the more code there is, the more the compiler has to work to look for patterns.
A long time ago in a different world, with a different compiler, we could change the cost
of a compilation by an order of magnitude by creating situations in which the compiler did
a lot of what was known as "omega motion", moving common subexpressions in the equivalent
of a switch statement to the end of the switch, but I think that is not what has happened
here. But it appears that a very large function is tweaking some sort of compiler bug.

Note: if you think the additional function calls will be "inefficient", you have a very
poorly formulated notion of program construction. You are saving nanoseconds in the calls
and probably expending several hundred micrososeconds to several milliseconds by using a
naive CArray::Add approach, so you are losing 3-4 orders of magnitude at an optimistic
level and losing 6 orders of magnitude as you take page faults each time the array expands
into nonresident storage, which probably happens a couple times during the 11,000
allocations. Concentrate on what matters, and code clarity is far more important that
peculiar notions of "efficiency", particularly with infinitesimally small values like
11,000 function calls are involved.

Remember that a single fragmentation of your executable on the disk will add something
like 10ms overhead to the startup, about 3,000 times larger than 33us. A single rotational
latency will add on the order of 70us if you have a 7200 RPM drive, PER ROTATIONAL MISS.
This means that if you are loading from a file, you could see massive variance just based
on timing of the file reads which will completely swamp any pitiful attempts to "optimize"
the number of function calls.

Answer: if your functions are that large, there is something definitely wrong with your
programming style. Split the program up more. This may mean you are no longer tickling the
bug.

An alternative is to turn off optimization for that module only.
                                                joe

On Sun, 31 Oct 2004 12:52:10 -0500, "Jim H" <nospam@jimsaccount.com> wrote:

>I have a MFC project that builds and compiles fine in VC6. When I open the
>project in VC7.1 I can't compile a release build with any optimizations
>turned on. CL.exe seems to hang during the "Generating Code..." phase of
>compiling a cpp file that includes afxtempl.h and uses a CArray<>. Debug
>builds fine and release with no optimizations builds fine.
>
>The file in question is a file that loads a global CArray with a little over
>11000 objects (each consisting of 5 small strings). Because of the limits
>of the VC6 compiler these 11000 CArray.Add()'s were broken down into 6
>functions (Load1() to Load6()). I've let the thing try to compile for 20
>minutes and it never returns. Like I said it compiles fine in VC6 with full
>optimizations and in VC7.1 in debug and release with no optimizations.
>
>Any ideas on how to get it to compile?
>
>Thanks,
>jim
>

Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm



Relevant Pages

  • Re: WaitForSingleObject() will not deadlock
    ... One is to hijack the semantics of volatile to disable compiler optimizations ... and otherwise let the compiler to agressive optimization. ... Agressive optimizations are the ones that work on the edge of the semantics of the ... Because the compiler can see into lock and unlock, it is able to reduce f ...
    (microsoft.public.vc.mfc)
  • Re: Really wierd bug
    ... > it has to be a compiler bug because it works fine for other population ... > My compiler is Compaq Visual Fortran 1997-1999. ... > with allocating the array sizes because I've defined the arrays as ... your program does indeed contain an array bounds error -- this ...
    (comp.lang.fortran)
  • Re: WaitForSingleObject() will not deadlock
    ... represent an incorrect implementation of the language. ... the *compiler* does not guarantee this. ... but to state it in terms of the execution instead of the formal semantics of the language ... as long as the optimizations do not change the semantics of the language). ...
    (microsoft.public.vc.mfc)
  • Re: optimized code
    ... > loop invariants are handled by the JIT not by the compiler fron-ends. ... generates the best optimized MSIL of any of the .NET languages. ... standard native code optimizations on MSIL code. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: c compilation - gcc vs visual c
    ... I recently compiled a numerically intensive c project under cygwin gcc ... MS focuses a lot more on specific optimizations, ... the simplest approach, however (and the one I currently use in my compiler), ... (silly code), are ones I focus on fixing. ...
    (comp.lang.c)