Nick Strupat
Nick Strupat

Reputation: 5063

Does making a member private or internal help the compiler make optimizations?

I was reading Eric Lippert's post

http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

So I am wondering what a developer can do to can help the C# compiler make optimizations, such as using the stack instead of the heap. For example, if you make a property internal to an assembly instead of protected/public, the compiler could consider that a guarantee that the property won't be seen outside the assembly and therefore not possibly referenced.

class Foo {
    internal Object Bar;
}

Obviously there is a fine line between fighting the compiler for optimizations and writing code that is actually more correct than your QA / unit testing requires as to help the compiler make stronger assumptions about it.

I am also wondering what other things can help the optimizer and are also worth the effort in the sense that they increase correctness.

Upvotes: 0

Views: 396

Answers (2)

Eric Lippert
Eric Lippert

Reputation: 660159

I am wondering what a developer can do to can help the C# compiler make optimizations, such as using the stack instead of the heap.

That's a noble aim but you're going about it backwards. Rather than saying "how can I write my program to help the compiler generate good code?" ask "is my program unacceptably slow?" If it is then use a profiler to find the slowest part, then figure out why it is so slow, and then ask "what can I do to make this code faster?"

For example: in Roslyn we discovered that a significant fraction of the time cost of the compiler was associated with garbage collection of the zillions of temporary objects that are created during semantic analysis. We decided to solve this problem using a variety of techniques, such as pooling strategies, lazy allocation, carefully tuned caches and an architecture that allowed large objects to be thrown away and recomputed later on demand if necessary.

Our attitude was always "we have to make sure this is fast" but the way we ensured that was not by trying to write the program up front to be fast. Instead what we did was wrote a performance test suite very early so that we could monitor every day whether yesterday's checkins had introduced a performance regression; this allowed us to quickly learn what techniques were making improvements and what were making regressions.

Performance is a feature, so design it like any other feature. Set goals, write tests that verify that you've met those goals. "Tips and tricks" for writing fast code are generally worthless; performance comes out of the process of using good empirical engineering techniques.

To address your specific question:

Does making a member private or internal help the compiler make optimizations?

The question presupposes that you'd take a public property and make it private because that's faster. But a property is public because a customer needs to use it. The reason to make a member private is because it's an implementation detail of the class, not because the compiler might be able to find an optimization.

There are a few ways that you can help the compiler make very small optimizations. For example:

class Fruit {}
class Apple : Fruit {}
class Orange : Fruit {}
...
Fruit[] fruits = new Apple[10];

Oh the pain. C# supports unsafe array covariance. When you say

fruits[0] = new Apple();

the runtime must generate a check that says "is fruits actually an Orange[]? Because if it is, we need to throw an exception." This is unavoidable. Now consider:

Apple[] apples = MakeAppleArray();
apples[0] = someApple;

Now, is the runtime check necessary here as well? Yes. apples might be GrannySmith[] and someApple might be RedDelicious, so the check is necessary. But suppose you said

sealed class Apple : Fruit {}

Now the runtime knows that apples cannot possibly really be GrannySmith[] because there is no such type. It might be able to save a few nanoseconds by knowing that Apple is sealed.

Again, saving a few nanoseconds is not a good reason to seal a class. Expressing the intention that the class was not designed for further inheritance is the reason to seal a class.

Similarly, if the compiler sees

X M() { return new X(); }
...
M().Foo(); // instance method

then the compiler will generate code that checks to see whether M() returned null before instance method Foo is called, because it is not smart enough to realize that M() never returns null. But if you say

(new X()).Foo();

then the compiler reasons "this either throws or produces a valid reference, therefore the null check can be removed". The compiler is smart here. Writing the code the second way instead of the first way could save up to two or three nanoseconds. It's not worth it. Don't write your code to try to take advantage of the compiler's little tricks; you will never, ever notice the difference. There are no programs in the app store that sold a million copies because they elided a null check and saved a nanosecond.

Upvotes: 10

JaredPar
JaredPar

Reputation: 754913

So I am wondering what a developer can do to can help the C# compiler make optimizations, such as using the stack instead of the heap.

Nothing. The C# compiler does very little in the way of optimizing. It certainly does nothing along the lines of using the stack over the heap based on the access modifiers you apply to your code.

The only way to control stack vs. heap at this time is to use struct instead of class. However that is still really a CLR decision, not C#. C# doesn't really have any notion of stack or heap, just lifetime of values.

Upvotes: 0

Related Questions