Click here to Skip to main content
15,860,972 members
Articles / Programming Languages / C#

Boosting Performance with Fields

Rate me:
Please Sign up or sign in to vote.
2.55/5 (9 votes)
17 Aug 2009CPOL6 min read 30.9K   7   23
A potentially significant amount of performance gain and code size reduction can be achieved by making use of internal fields rather than designing applications with a blanket use of public properties.

Introduction

A potentially significant amount of performance gain and code size reduction can be achieved by making use of internal fields rather than designing applications with a blanket use of public properties. Public properties are frequently blindly considered a “good programming practice” without giving thought to whether that practice is applicable.

Optimization removes much, but not all, of the penalty of properties in the .NET environment. We present some of the philosophical arguments in the conclusion.

Arguments for Public Properties

When a value requires exposure to other developer’s assemblies, defining it as a property has merit. For example, in version 1 of our assembly we define the following property and field:

C#
public int MyProperty { get; set; }

public int MyField;

In time, others are now using our assembly and are dependent on it. Later we find an issue that we must address, such as the values must always be positive. We can change our property as below to be tolerant to consumers of our assembly passing negative values.

C#
public int MyProperty
{
    get { return this.myProperty; }
    set { this.myProperty = value >= 0 ? value : 0; }
}
private int myProperty;

Users of our assembly do not have to recompile to make use of our update. However, we cannot do the same to our field. To add the value checking code to our field, we must first turn it into a property, and if we do so, we break compatibility with previous versions. This would make public fields not a “good programming practice.”

Mechanics of Properties and Fields

There is a cost to using a property rather than a field. A field is essentially a location in memory that we can get and set values with a single instruction to the CPU (“mov” in the case of the X86). However a property is a way of auto-generating code. The two methods below are the resulting code:

C#
public int get_MyProperty()
{
    return this.myProperty;
}
public void set_MyProperty(int value)
{
    this.myProperty = value >= 0 ? value : 0;
}
private int myProperty;

We are no longer using a single CPU instruction to access our value, but are calling methods to get or set the value. The CPU must now execute a call instruction to the method and the method must do the “mov” instruction and then a return instruction. Adding to the additional instructions are the pushing and popping of the instruction pointer to the stack. The result is at least five times the amount of work for a property as compared to a field. There are many techniques used in CPU hardware to increase efficiency, such as doing the pushing and popping in parallel, but that is beyond our scope.

Internal Fields

We see that using properties for public values has merit and a cost that we must bear. However, this weight does not have to be applied to values that are used internally within our assembly. If a given value, at least for the current version, is used only within our assembly, we should not expose it publicly, but rather keep it internal as below.

C#
internal int MyValue;

The overhead of properties is eliminated by using a field. If we are now coding version 2 of our assembly and find that we have to add our validation logic, we can simply change our field into a property and recompile. Typically, no other parts of our assembly are impacted, and no compatibility issues arise.

C#
internal int MyValue
{
    get { return this. myValue; }
    set { this. myValue = value >= 0 ? value : 0; }
}
private int myValue;

Accessing Public Properties as Internal Fields

We can gain some internal efficiency with public properties by internally exposing the underlying values. This allows our assembly to make use of the value as a field while allowing for updates in future versions.

C#
public int MyProperty
{
    get { return this.myProperty; }
    set { this.myProperty = value; }
}
internal int myProperty;

If we find we have to add our validation logic, we can do a search on all internal references to our field and change them as appropriate to using the public property. Since the changes we are making impact only our assembly, there is no impact on other users.

Public Fields When We Own the Solution

When multiple assemblies are used in our solution, but those assemblies are not shared outside of our solution, we can make use of public fields in the same way we have described for internal fields.

Even when we have a large team working on a single solution, we can expose values as public fields, as the “MyValue” example above. Anyone can change a field into a property when necessary without disrupting the efforts of the other members of the team. By employing this policy, we can achieve a balance of efficiency and updatability.

Optimization Removes Much of the Weight

The compilers in the Microsoft .NET Framework offer significant optimization. The “debug” version performs as described above, but the “release” code removes the call to the getter and setter and accesses the backing field directly.

This optimization performs remarkably, but is not complete. Incrementing a field is a single instruction, while incrementing a property remains three. This optimization may also be present in future versions of the compiler.

libraryClass.MyField++;
inc        dword ptr [esi+8]
libraryClass.MyProperty++;
mov        eax,dword ptr [esi+4]
inc        eax
mov        dword ptr [esi+4],eax

Note: To view the disassembly of optimized code in Visual Studio 2008, you must change some of the default options. Click "Tools" then "Options".
In the "Debugging General" uncheck "Enable Just My Code (Managed Only)" and "Suppress JIT optimization on module Load (Managed Only)".

However, a property’s getter and setter definitions remain and the JIT compiler must perform the optimization each time the application loads. Fields are, in essence, optimized before the JIT compiler starts, and require one entry into the assembly’s manifest which results in a smaller file.

Philosophical Arguments

Some will argue that it is simplest to use properties always and let the compiler make the decisions. We suggest that when you write code, you should write what you intend to have executed. Properties sometimes execute as fields, whereas fields always execute as fields.

If you write for more than one environment, then you cannot assume the optimizations will carry forward. The concepts of properties and fields are essentially universal, even with 8-bit embedded processors, but optimization is not.

In many cases, such as many data binding scenarios, properties are required and fields are not an option.

Many times, especially in internal applications, the debug version is the version that goes into production use. When this is the case, the optimization advantage is gone.

Compile time during application development, application start time, and file sizes are all impacted by the choice of properties versus fields. For one instance, the impact is insignificant. For complex applications, the impact is real.

Conclusion

The great value of public properties comes into play when we are developing assemblies that are used by others outside of our solution. When we own the solution and make blind use of properties, we add significant, unnecessary overhead to our development effort and impair the application’s performance.

For a solo programmer or a large team, a refined policy of using fields and properties wisely can result in a performance gain and code size reduction.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder ShofarNexus Corporation
United States United States
ShofarNexus™ is software project started in 1998 with a lot of testing and rejecting of methodologies. Our goals were fast startup and execution, a clean presentation and reliable data distribution. We take ReST to the extreme. We focus some on eye-candy and mostly on the meat and vegetables that are good for business.

ShofarNexus™ mentality is well described by Antoine de Saint-Exupéry who wrote “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”

ShofarNexus™ is single-handedly written by John Kozlowski, with over 35 years of software development experience and a lot of hardware design in the first two decades.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Heywood18-Aug-09 3:39
Heywood18-Aug-09 3:39 
GeneralMy vote of 1 Pin
srikalwa17-Aug-09 19:12
srikalwa17-Aug-09 19:12 
Generalwtf ;/ Pin
radioman.lt17-Aug-09 18:24
radioman.lt17-Aug-09 18:24 
GeneralRe: wtf ;/ Pin
Heywood18-Aug-09 3:46
Heywood18-Aug-09 3:46 
GeneralRe: wtf ;/ Pin
r_hyde18-Aug-09 6:46
r_hyde18-Aug-09 6:46 
For some reason that I have yet to be let in on, at my company we always release the debug versions of our internal software to production. For better or for worse, the author may actually be right about this one.
GeneralMy vote of 1 Pin
Günther M. FOIDL9-Aug-09 3:54
Günther M. FOIDL9-Aug-09 3:54 
GeneralRe: My vote of 1 Pin
ShofarNexus17-Aug-09 12:40
ShofarNexus17-Aug-09 12:40 
GeneralMy vote of 2 Pin
talley9-Aug-09 3:50
talley9-Aug-09 3:50 
GeneralMy vote of 2 Pin
BoBsEd9-Aug-09 1:27
BoBsEd9-Aug-09 1:27 
GeneralMy vote of 2 Pin
Christoph Weber8-Aug-09 10:14
Christoph Weber8-Aug-09 10:14 
GeneralRe: My vote of 2 Pin
ShofarNexus8-Aug-09 11:56
ShofarNexus8-Aug-09 11:56 
GeneralRe: My vote of 2 Pin
Heywood18-Aug-09 3:55
Heywood18-Aug-09 3:55 
GeneralMoot Point Pin
Justin Helsley8-Aug-09 9:24
Justin Helsley8-Aug-09 9:24 
GeneralRe: Moot Point Pin
ShofarNexus8-Aug-09 9:51
ShofarNexus8-Aug-09 9:51 
GeneralRe: Moot Point Pin
Justin Helsley8-Aug-09 10:02
Justin Helsley8-Aug-09 10:02 
GeneralRe: Moot Point Pin
ShofarNexus8-Aug-09 11:49
ShofarNexus8-Aug-09 11:49 
GeneralRe: Moot Point Pin
Justin Helsley8-Aug-09 12:05
Justin Helsley8-Aug-09 12:05 
GeneralRe: Moot Point Pin
ShofarNexus8-Aug-09 13:05
ShofarNexus8-Aug-09 13:05 
GeneralRe: Moot Point Pin
FZelle9-Aug-09 1:03
FZelle9-Aug-09 1:03 
GeneralRe: Moot Point Pin
stikves9-Aug-09 3:14
stikves9-Aug-09 3:14 
GeneralRe: Moot Point Pin
Justin Helsley9-Aug-09 4:58
Justin Helsley9-Aug-09 4:58 
GeneralRe: Moot Point Pin
ShofarNexus17-Aug-09 12:38
ShofarNexus17-Aug-09 12:38 
GeneralInteresting Pin
Trollslayer8-Aug-09 7:27
mentorTrollslayer8-Aug-09 7:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.