Release build not optimizing

B

Brett Romero

I'm using MSBUILD to build release and debug versions of a winform
project (VS.NET 2005). The project file has conditionals to file
reference DLLs depending on the build configuration (debug or
release). The generated EXE PDB file for release is 2KB smaller than
the debug version. However, the EXEs are exactly the same size.
Release is set to optimize code but why are these EXEs the same size?
The program also loads the same with both versions. Release should be
faster.

Thanks,
Brett
 
M

Marc Gravell

Release is set to optimize code but why are these EXEs the same size?
Alignment perhaps?
Release should be faster.
It isn't a step-change, however; especially if you are comparing DEBUG
outside the debugger to RELEASE outside the debugger, How are you
measuring the [non-]change?

The main thing I would check is: is the MSBUILD output consistent with
the VS output? To check you have the right MSBUILD params (no slight
intended).

Marc
 
B

Brett Romero

Release is set to optimize code but why are these EXEs the same size?

Alignment perhaps?
Release should be faster.

It isn't a step-change, however; especially if you are comparing DEBUG
outside the debugger to RELEASE outside the debugger, How are you
measuring the [non-]change?

File size in bytes.
The main thing I would check is: is the MSBUILD output consistent with
the VS output?
From what I can tell by looking at DLL and PDB file sizes, it is the consistent.

To check you have the right MSBUILD params (no slight
intended).

Marc

VS.NET is producing the same size EXEs as well. Isn't that just using
MSBUILD the same way I am?

When I build the debug version in VS.NET, the project file references
debug versions of the DLLs. When I build the release version, I
change out the DLLs to reference their release versions. I'm doing
all of that just to test why they are the same.
 
J

Jon Skeet [C# MVP]

Brett Romero said:
I'm using MSBUILD to build release and debug versions of a winform
project (VS.NET 2005). The project file has conditionals to file
reference DLLs depending on the build configuration (debug or
release). The generated EXE PDB file for release is 2KB smaller than
the debug version. However, the EXEs are exactly the same size.
Release is set to optimize code but why are these EXEs the same size?
The program also loads the same with both versions. Release should be
faster.

You're assuming that smaller==faster. Have you actually timed them to
see whether the release build *isn't* faster?

Note that most of the optimisation in .NET is performed by the JIT
compiler anyway, rather than the C# compiler.
 
B

Brett Romero

You're assuming that smaller==faster. Have you actually timed them to
see whether the release build *isn't* faster?

With most of the projects I've compiled, the release is smaller. In
this particular case, both versions load the same. I haven't gone in
depth to explore any JITing differences. However, upon load up, there
should be a large amount of JITing going on for this app. In that
regard, they load at the same speed.
 
J

Jon Skeet [C# MVP]

With most of the projects I've compiled, the release is smaller. In
this particular case, both versions load the same. I haven't gone in
depth to explore any JITing differences. However, upon load up, there
should be a large amount of JITing going on for this app. In that
regard, they load at the same speed.

The same amount of JITting will happen either way though.

It's not entirely clear what's making you uncomfortable other than the
size of the assembly, which isn't terribly important in itself IMO. As
I say, most of the optimisation in C#/.NET occurs at the JIT level
rather than the C# compiler level.

There's one way you can test whether it's optimising or not, however.
Make a public method which initializes a local variable which isn't
then used, e.g.
int dummy = 10;

You'll get a warning when you compile, but the IL for optimised code
will be different to non-optimised code - in the optimised code, the
assignment won't take place at all (and the variable won't appear in
the locals list), whereas in non-optimised mode it will still be
there. You can verify this with ildasm. So, this way you can check
whether or not your assembly really is being compiled with
optimisation on or not.

Jon
 
M

Marc Gravell

Also - far less formal, but debug code also tends to include a few
NOPs etc at the head/foot of methods. I've never bothered looking into
why - presumably they are reference points for debugging symbols, or
manual alignment or some-such.

Marc
 
B

Brett Romero

It's not entirely clear what's making you uncomfortable other than the
size of the assembly, which isn't terribly important in itself IMO.

The load time speed is an issue as well. Release should load faster.
I'll try the dummy code method. Thanks.
 
M

Marc Gravell

What makes you say that? Unless you are thrashing the CPU, you aren't
likely to see much. In most common situations, the speed difference
isn't very easy to see... it isn't as though DEBUG deliberately runs
slowly... Fusion still has to load and pre-process the assemblies; any
network (database etc) access will still take a while...

Running with a debugger attached is entirely different of course;
RELEASE standalone will be noticeably quicker than DEBUG in the IDE.

Marc
 
B

Brett Romero

There's one way you can test whether it's optimising or not, however.
Make a public method which initializes a local variable which isn't
then used, e.g.
int dummy = 10;

I added this several times just to be sure there is a noticeable
difference in the EXE file sizes:

public void testmx( )
{
int i = 3;
int j = 4 + 3;
Int64 k = 5000 + 600000000;

}

Release and debug builds produce EXEs that are still the same size.
However, their corresponding PDBs differ by 2KB. I'm confused by
this. Shouldn't the optimizer remove this superfluous code since it
isn't being used, giving a smaller footprint to the release build?
 
B

Ben Voigt

Brett Romero said:
I added this several times just to be sure there is a noticeable
difference in the EXE file sizes:

public void testmx( )
{
int i = 3;
int j = 4 + 3;
Int64 k = 5000 + 600000000;

}

Release and debug builds produce EXEs that are still the same size.
However, their corresponding PDBs differ by 2KB. I'm confused by
this. Shouldn't the optimizer remove this superfluous code since it
isn't being used, giving a smaller footprint to the release build?

It's a public method, and also .NET has run-time reflection capabilities.
Determining that a function is not used would be halting-problem difficult,
and only valid for that particular version of all assemblies.
 
B

Ben Voigt

Brett Romero said:
The load time speed is an issue as well. Release should load faster.
I'll try the dummy code method. Thanks.

No, release should load slower, because the optimizing JIT compiler is
enabled. Load time is when the compiler runs, turning on the optimizer pass
will slow it down. Only with ngen-ed assemblies will you see the load time
decrease.
 
J

Jon Skeet [C# MVP]

Release and debug builds produce EXEs that are still the same size.

There are internal block sizes to consider - just removing a line of
code can change the IL without changing the code size. You need to look
at the IL instead.
However, their corresponding PDBs differ by 2KB. I'm confused by
this. Shouldn't the optimizer remove this superfluous code since it
isn't being used, giving a smaller footprint to the release build?

Why not use ildasm and *check* rather than going just by file size?
 
J

Jon Skeet [C# MVP]

Ben Voigt said:
It's a public method, and also .NET has run-time reflection capabilities.
Determining that a function is not used would be halting-problem difficult,
and only valid for that particular version of all assemblies.

It shouldn't remove the method itself, but it *can* remove the local
variables. (The additions wouldn't be in the IL to start with.)
 
B

Ben Voigt

Jon Skeet said:
It shouldn't remove the method itself, but it *can* remove the local
variables. (The additions wouldn't be in the IL to start with.)

That's true, but I'm pretty sure "superfluous code" meant the whole
function. As you mention in your other post, small changes within a
function needn't change the IL image size, because of block alignment.
 
B

Brett Romero

Why not use ildasm and *check* rather than going just by file size?

I did view both the debug and release versions of the EXE in ildasm.
I see the bogus testmx() methods in both versions. If I'm building
the release to optimize, shouldn't those be removed? This is the
syntax I'm using:


C:\>msbuild "c:\apps\myproj.csproj" /t:Rebuild /
p:Configuration=Release /property:warninglevel=0 /l:FileLogge
r,Microsoft.Build.Engine;verbosity=minimal;logfile=DEBUGLog.txt

In the project file XML for the release, I have
<Optimize>true</Optimize>

and false for debug.
 
J

Jon Skeet [C# MVP]

Brett Romero said:
I did view both the debug and release versions of the EXE in ildasm.
I see the bogus testmx() methods in both versions. If I'm building
the release to optimize, shouldn't those be removed?

No. As Ben said, it's a public method - it can't be removed. Look at
the IL within the method though.
 
W

Willy Denoyette [MVP]

Jon Skeet said:
No. As Ben said, it's a public method - it can't be removed. Look at
the IL within the method though.

And even when it was a private method, it wouldn't be removed.

Willy.
 
B

Brett Romero

No. As Ben said, it's a public method - it can't be removed. Look at
the IL within the method though.

Ok, yes - I see the difference. The method body has been optimized.
Since that is the case, why isn't the optimized EXE footprint
smaller? Bytes have been removed. The manifest is stored in the EXE
and that's where ILDASM gets it's info from right?
 
J

Jon Skeet [C# MVP]

Willy Denoyette said:
And even when it was a private method, it wouldn't be removed.

Would it be illegal to do so though, as an academic question? I know
the method would still be available to reflection, but I'm not sure
whether that really counts in terms of correctness.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top