Is the Microsoft recommendation to use C# properties applicable to game development?Is Kip R. Irvine's claim of Assembly being practical for game development accurate?How to describe the performance requirements for a PC game?Avoiding memory allocation in Android game developmentHow to access an animation properties from the animator?Java 2D Game Development - Best Performance With RenderingCan I use inheritance to inherit properties from the editor?Why does Unity use reflection to get the update method?OnInspectorGUI Custom properties are not displayed in the right order
Why is there not a willingness from the world to step in between Pakistan and India?
What is the name of this plot that has rows with two connected dots?
Group riding etiquette
Many many thanks
What is the sound/audio equivalent of "unsightly"?
Can I create something like a macro in Numbers?
Fantasy Macro Economics: What would Merfolk Trade?
view is not fixed completely regardless of vewpoint
To what extent should we fear giving offense?
If I said I had $100 when asked, but I actually had $200, would I be lying by omission?
Why does glibc's strlen need to be so complicated to run fast?
Stolen MacBook should I worry about my data?
Book featuring a child learning from a crowdsourced AI book
How to prevent a hosting company from accessing a VM's encryption keys?
Do Rome and Persia's kingdoms still exist?
How do we improve collaboration with problematic tester team?
Why can't you say don't instead of won't?
What is Soda Fountain Etiquette?
Find feasible point in polynomial time in linear programming
Could the UK amend the European Withdrawal Act and revoke the Article 50 invocation?
Is it unusual for a math department not to have a mail/web server?
Time difference between banns and marriage
Why was this commercial plane highly delayed mid-flight?
Did ancient peoples ever hide their treasure behind puzzles?
Is the Microsoft recommendation to use C# properties applicable to game development?
Is Kip R. Irvine's claim of Assembly being practical for game development accurate?How to describe the performance requirements for a PC game?Avoiding memory allocation in Android game developmentHow to access an animation properties from the animator?Java 2D Game Development - Best Performance With RenderingCan I use inheritance to inherit properties from the editor?Why does Unity use reflection to get the update method?OnInspectorGUI Custom properties are not displayed in the right order
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
I get that sometimes you need properties, like:
public int[] Transitions get; set;
or:
[SerializeField] private int[] m_Transitions;
public int[] Transitions get return m_Transitions; set m_Transitions = value;
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible. My impression from things I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
Am I right to constantly ignore Visual Studio's suggestions to not use public fields? (Note that we do use int Foo get; private set;
where there is an advantage in showing the intended usage.)
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
unity performance optimization
$endgroup$
add a comment |
$begingroup$
I get that sometimes you need properties, like:
public int[] Transitions get; set;
or:
[SerializeField] private int[] m_Transitions;
public int[] Transitions get return m_Transitions; set m_Transitions = value;
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible. My impression from things I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
Am I right to constantly ignore Visual Studio's suggestions to not use public fields? (Note that we do use int Foo get; private set;
where there is an advantage in showing the intended usage.)
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
unity performance optimization
$endgroup$
34
$begingroup$
Always verify with a profiler before believing something is "slow". I was told something was "slow" and the profiler told me it had to execute 500,000,000 times to lose a half second. As it would never execute more than a few hundred times in a frame, I decided it was irrelevant.
$endgroup$
– Almo
Aug 15 at 13:46
5
$begingroup$
I've found that a little bit of abstraction here and there helps to apply low-level optimizations more widely. For instance, I've seen numerous plain C projects using various kinds of of linked-lists, which are dreadfully slow compared to contiguous arrays (e.g. the backing forArrayList
). This is because C has no generics, and these C programmers likely found it easier to repeatedly re-implement linked-lists than to do the same forArrayLists
's resizing algorithm. If you come up with a good low-level optimization, encapsulate it!
$endgroup$
– hegel5000
Aug 15 at 17:46
3
$begingroup$
@Almo Do you apply that same logic to operations that occur in 10,000 different places? Because that is class member access. Logically you should be multiplying the performance cost by 10K before deciding that class of optimization doesn't matter. And 0.5 ms is a better rule of thumb for when the performance of your game will be ruined, not half a second. Your point still stands, though I don't think the right action is as clear as you make it out to be.
$endgroup$
– piojo
Aug 16 at 3:08
5
$begingroup$
You have 2 horses. Race them.
$endgroup$
– Mast
Aug 16 at 11:48
$begingroup$
@piojo I do not. Some thought must always go into these things. In my case, it was for loops in UI code. One UI instance, few loops, few iterations. For the record, I upvoted your comment. :)
$endgroup$
– Almo
Aug 16 at 16:14
add a comment |
$begingroup$
I get that sometimes you need properties, like:
public int[] Transitions get; set;
or:
[SerializeField] private int[] m_Transitions;
public int[] Transitions get return m_Transitions; set m_Transitions = value;
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible. My impression from things I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
Am I right to constantly ignore Visual Studio's suggestions to not use public fields? (Note that we do use int Foo get; private set;
where there is an advantage in showing the intended usage.)
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
unity performance optimization
$endgroup$
I get that sometimes you need properties, like:
public int[] Transitions get; set;
or:
[SerializeField] private int[] m_Transitions;
public int[] Transitions get return m_Transitions; set m_Transitions = value;
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible. My impression from things I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
Am I right to constantly ignore Visual Studio's suggestions to not use public fields? (Note that we do use int Foo get; private set;
where there is an advantage in showing the intended usage.)
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
unity performance optimization
unity performance optimization
asked Aug 15 at 7:51
piojopiojo
4154 silver badges9 bronze badges
4154 silver badges9 bronze badges
34
$begingroup$
Always verify with a profiler before believing something is "slow". I was told something was "slow" and the profiler told me it had to execute 500,000,000 times to lose a half second. As it would never execute more than a few hundred times in a frame, I decided it was irrelevant.
$endgroup$
– Almo
Aug 15 at 13:46
5
$begingroup$
I've found that a little bit of abstraction here and there helps to apply low-level optimizations more widely. For instance, I've seen numerous plain C projects using various kinds of of linked-lists, which are dreadfully slow compared to contiguous arrays (e.g. the backing forArrayList
). This is because C has no generics, and these C programmers likely found it easier to repeatedly re-implement linked-lists than to do the same forArrayLists
's resizing algorithm. If you come up with a good low-level optimization, encapsulate it!
$endgroup$
– hegel5000
Aug 15 at 17:46
3
$begingroup$
@Almo Do you apply that same logic to operations that occur in 10,000 different places? Because that is class member access. Logically you should be multiplying the performance cost by 10K before deciding that class of optimization doesn't matter. And 0.5 ms is a better rule of thumb for when the performance of your game will be ruined, not half a second. Your point still stands, though I don't think the right action is as clear as you make it out to be.
$endgroup$
– piojo
Aug 16 at 3:08
5
$begingroup$
You have 2 horses. Race them.
$endgroup$
– Mast
Aug 16 at 11:48
$begingroup$
@piojo I do not. Some thought must always go into these things. In my case, it was for loops in UI code. One UI instance, few loops, few iterations. For the record, I upvoted your comment. :)
$endgroup$
– Almo
Aug 16 at 16:14
add a comment |
34
$begingroup$
Always verify with a profiler before believing something is "slow". I was told something was "slow" and the profiler told me it had to execute 500,000,000 times to lose a half second. As it would never execute more than a few hundred times in a frame, I decided it was irrelevant.
$endgroup$
– Almo
Aug 15 at 13:46
5
$begingroup$
I've found that a little bit of abstraction here and there helps to apply low-level optimizations more widely. For instance, I've seen numerous plain C projects using various kinds of of linked-lists, which are dreadfully slow compared to contiguous arrays (e.g. the backing forArrayList
). This is because C has no generics, and these C programmers likely found it easier to repeatedly re-implement linked-lists than to do the same forArrayLists
's resizing algorithm. If you come up with a good low-level optimization, encapsulate it!
$endgroup$
– hegel5000
Aug 15 at 17:46
3
$begingroup$
@Almo Do you apply that same logic to operations that occur in 10,000 different places? Because that is class member access. Logically you should be multiplying the performance cost by 10K before deciding that class of optimization doesn't matter. And 0.5 ms is a better rule of thumb for when the performance of your game will be ruined, not half a second. Your point still stands, though I don't think the right action is as clear as you make it out to be.
$endgroup$
– piojo
Aug 16 at 3:08
5
$begingroup$
You have 2 horses. Race them.
$endgroup$
– Mast
Aug 16 at 11:48
$begingroup$
@piojo I do not. Some thought must always go into these things. In my case, it was for loops in UI code. One UI instance, few loops, few iterations. For the record, I upvoted your comment. :)
$endgroup$
– Almo
Aug 16 at 16:14
34
34
$begingroup$
Always verify with a profiler before believing something is "slow". I was told something was "slow" and the profiler told me it had to execute 500,000,000 times to lose a half second. As it would never execute more than a few hundred times in a frame, I decided it was irrelevant.
$endgroup$
– Almo
Aug 15 at 13:46
$begingroup$
Always verify with a profiler before believing something is "slow". I was told something was "slow" and the profiler told me it had to execute 500,000,000 times to lose a half second. As it would never execute more than a few hundred times in a frame, I decided it was irrelevant.
$endgroup$
– Almo
Aug 15 at 13:46
5
5
$begingroup$
I've found that a little bit of abstraction here and there helps to apply low-level optimizations more widely. For instance, I've seen numerous plain C projects using various kinds of of linked-lists, which are dreadfully slow compared to contiguous arrays (e.g. the backing for
ArrayList
). This is because C has no generics, and these C programmers likely found it easier to repeatedly re-implement linked-lists than to do the same for ArrayLists
's resizing algorithm. If you come up with a good low-level optimization, encapsulate it!$endgroup$
– hegel5000
Aug 15 at 17:46
$begingroup$
I've found that a little bit of abstraction here and there helps to apply low-level optimizations more widely. For instance, I've seen numerous plain C projects using various kinds of of linked-lists, which are dreadfully slow compared to contiguous arrays (e.g. the backing for
ArrayList
). This is because C has no generics, and these C programmers likely found it easier to repeatedly re-implement linked-lists than to do the same for ArrayLists
's resizing algorithm. If you come up with a good low-level optimization, encapsulate it!$endgroup$
– hegel5000
Aug 15 at 17:46
3
3
$begingroup$
@Almo Do you apply that same logic to operations that occur in 10,000 different places? Because that is class member access. Logically you should be multiplying the performance cost by 10K before deciding that class of optimization doesn't matter. And 0.5 ms is a better rule of thumb for when the performance of your game will be ruined, not half a second. Your point still stands, though I don't think the right action is as clear as you make it out to be.
$endgroup$
– piojo
Aug 16 at 3:08
$begingroup$
@Almo Do you apply that same logic to operations that occur in 10,000 different places? Because that is class member access. Logically you should be multiplying the performance cost by 10K before deciding that class of optimization doesn't matter. And 0.5 ms is a better rule of thumb for when the performance of your game will be ruined, not half a second. Your point still stands, though I don't think the right action is as clear as you make it out to be.
$endgroup$
– piojo
Aug 16 at 3:08
5
5
$begingroup$
You have 2 horses. Race them.
$endgroup$
– Mast
Aug 16 at 11:48
$begingroup$
You have 2 horses. Race them.
$endgroup$
– Mast
Aug 16 at 11:48
$begingroup$
@piojo I do not. Some thought must always go into these things. In my case, it was for loops in UI code. One UI instance, few loops, few iterations. For the record, I upvoted your comment. :)
$endgroup$
– Almo
Aug 16 at 16:14
$begingroup$
@piojo I do not. Some thought must always go into these things. In my case, it was for loops in UI code. One UI instance, few loops, few iterations. For the record, I upvoted your comment. :)
$endgroup$
– Almo
Aug 16 at 16:14
add a comment |
7 Answers
7
active
oldest
votes
$begingroup$
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
Not necessarily. Just like in application software, there is code in a game which is performance-critical and code which is not.
If the code is executed several thousand times per frame, then such a low-level optimization might make sense. (Although you might first want to check first if it is actually necessary to call it that often. The fastest code is code you don't run)
If the code is executed once every couple seconds, then readability and maintainability is far more important than performance.
I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
With trivial properties in the style of int Foo get; private set;
you can be pretty certain that the compiler will optimize the property wrapper away. But:
- if you actually have an implementation, then you can not be that sure anymore. The more complex that implementation, the less likely that the compiler will be able to inline it.
- Properties can hide complexity. This is a double-edged sword. On the one hand, it makes your code more readable and changeable. But on the other hand, another developer who accesses a property of your class might think they are just accessing a single variable and not realize how much code you've actually hidden behind that property. When a property starts to become computationally expensive, then I tend to refactor it into an explicit
GetFoo()
/SetFoo(value)
method: To imply that there is a lot more happening behind the scenes. (or if I need to be even more sure that others get the hint:CalculateFoo()
/SwitchFoo(value)
)
$endgroup$
$begingroup$
Accessing a field within a non-read-only public field of structure type is fast, even if that field is within a structure that is within a structure etc., provided that the top-level object is either a non-read-only class field or a non-read-only free-standing variable. Structures can be quite large without adversely affecting performance if these conditions apply. Breaking this pattern will cause slowdown proportional to structure size.
$endgroup$
– supercat
Aug 15 at 20:06
5
$begingroup$
"then I tend to refactor it into an explicit GetFoo() / SetFoo(value) method:" - Good point, I tend to move heavy operations out of properties into methods.
$endgroup$
– Mark Rogers
Aug 15 at 20:53
$begingroup$
Is there a way to confirm that the Unity 3D compiler makes the optimization you mention (in IL2CPP and Mono builds for Android)?
$endgroup$
– piojo
Aug 16 at 5:02
9
$begingroup$
@piojo As with most performance questions, the simplest answer is "just do it". You have the code ready - test the difference between having a field and having a property. The implementation details are only worth investigating when you can actually measure an important difference between the two approaches. In my experience, if you write everything to be as fast as possible, you limit the available high level optimizations, and just try to race the low level parts ("can't see forest for the trees"). E.g. finding ways to skipUpdate
entirely will save you more time than makingUpdate
fast.
$endgroup$
– Luaan
Aug 16 at 8:16
add a comment |
$begingroup$
When in doubt, use best practices.
You are in doubt.
That was the easy answer. Reality is more complex, of course.
First, there's the myth that game programming is ultra super high performance programming and everything has to be as fast as possible. I classify game programming as performance aware programming. The developer must be aware of performance constraints and work within them.
Second, there's the myth that making every single thing as fast as possible is what makes a program run fast. In reality, identifying and optimizing bottlenecks is what makes a program fast, and that is much easier/cheaper/faster to do if the code easy to maintain and modify; extremely optimized code is hard to maintain and modify. It follows that in order to write extremely optimized programs, you have to use extreme code optimization as often as needed and as rarely as possible.
Third, the benefit of properties and accessors is that they are robust to change, and thus make code easier to maintain and modify - which is something you need to write fast programs. Want to throw an exception whenever someone wants to set your value to null? Use a setter. Want to send a notification whenever the value changes? Use a setter. Want to log the new value? Use a setter. Want to do lazy initialization? Use a getter.
And fourth, personally I don't follow Microsoft's best practice in this instance. If I need a property with trivial and public getters and setters, I just use a field, and simply change it to a property when I need to. However, I very rarely need such a trivial property - it's far more common that I want to check for boundary conditions, or want to make the setter private.
$endgroup$
add a comment |
$begingroup$
It is very easy for the .net runtime to inline simple properties, and often it does. But, this inlining is normally disabled by profilers, hence it is easy to be misled and think that changing a public property to a public field will speed up software.
In code that is called by other code that will not be recompiled when your code is recompiled there is a good case for using properties, as changing from a field to a property is a breaking change. But for most code, other than being able to set a breakpoint on the get/set, I have never seen benefits in using a simple property compared to a public field.
The primary reason I used properties in my 10 years as a professional C# programmer was to stop other programmers telling me I was not keeping to the coding standard. This was a good tradeoff, as hardly ever was there a good reason not to use a property.
$endgroup$
add a comment |
$begingroup$
Structs and naked fields will ease interoperability with some not managed APIs. Often you will find that the low level API wants to access the values by reference, which is good for performance (as we avoid an unnecessary copy). Using properties is an obstacle to that, and often times the wrapper libraries will do copies for ease of use, and sometimes for security.
Because of that, you will often get better performance having vector and matrix types that do not have properties but naked fields.
Best practices are not creating in vaccum. Despite some cargo cult, in general best practices are there for a good reason.
In this case, we have a couple:
A property allows you to change the implementation without changing the client code (on a binary level, it is possible to change a field to a property without changing the client code on a source level, however it will compile to something different after the change). That means, that by using a property from the start, the code that references yours will not have to be recompiled just to change what the property does internally.
If not all the possible values of the fields of your type are valid states, then you do not want to expose them to client code that code modify it. Thus, if some combinations of values are invalid, you want to keep the fields private (or internal).
I have been saying client code. That means code that calls into yours. If you are not making a library (or even making library but using internal instead of public), you can usually get away with it and some good discipline. In that situation the best practice of using properties is there to prevent you from shooting yourself in the foot. Furthermore, it is much easier to reason about code if you can see all the places where a field can change in a single file, instead of having to worry on whatever or not it is being modified somewhere else. In fact, properties are also good to put breakpoints when you are figuring out what went wrong.
Yes, there is value is seeing what is being done int industry. However, do you have a motivation to go against the best practices? or are you just going against the best practices – making the code harder to reason about – just because somebody else did it? Ah, by the way, "others do it" is how you start a cargo cult.
So... Is your game running slow? You are better of devoting time to figure out the bottleneck and fixing that, instead of speculating what could it be. You can rest assured that the compiler will do plenty of optimizations, because of that, chances are you are looking at the wrong problem.
On the flip side, if you are deciding what to do to begin with, you should worry about what algorithms and data structures first, instead of worrying about smaller details such as fields vs properties.
Finally, do you earn something by going against best practices?
For the particulars of you case (Unity and Mono for Android), does Unity takes values by reference? If it doesn't, it will copy the values anyway, no performance gain there.
If it does, if you are passing this data to an API that takes ref. Does it make sense to make the field public, or you could make the type able to call the API directly?
Yes, of course, there could be optimizations that you could do by using structs with naked fields. For example, you access them with pointers Span<T>
, or similar. They are also compact on memory, making them easy to serialize to send over the network or put in permanent storage (and yes those are copies).
Now, have you picked the right algorithms and structures, if they turn out to be a bottleneck, then you decide what is the best way to fix it... that could be structs with naked fields or not. You will be able to worry about that if and when it happens. Meanwhile you can worry about more important matters such as making a good or fun game worth playing.
$endgroup$
add a comment |
$begingroup$
...my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
:
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
You are right to be aware that premature optimisation is bad but that is only half the story (see the full quote below). Even in game development, not everything needs to be as fast as possible.
First make it work. Only then, optimise the bits that need it. That's not to say that the first draft can be messy or needlessly inefficient but that optimisation is not a priority at this stage.
"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming." Donald Knuth, 1974.
$endgroup$
add a comment |
$begingroup$
For basic stuff like that, the C# optimizer's going to get it right anyway. If you worry about it (and if you worry about it for more than 1% of your code, you're doing it wrong) an attribute was created for you. The attribute [MethodImpl(MethodImplOptions.AggressiveInlining)]
greatly increases the chance a method will be inlined (property getters and setters are methods).
$endgroup$
add a comment |
$begingroup$
Exposing structure-type members as properties rather than fields will often yield poor performance and semantics, especially in cases where structures are actually treated as structures, rather than as "quirky objects".
A structure in .NET is a collection of fields duct-taped together, and which can for some purposes be treated as a unit. The .NET Framework is designed to allow structures to be used in much the same way as class objects, and there are times this can be convenient.
Much of the advice surrounding structures is predicated on the notion that programmers will be wanting to use structures as objects, rather than as taped-together collections of fields. On the other hand, there are many cases where it can be useful to have something that behaves as a taped-together bunch of fields. If that's what one needs, the .NET advice will add needless work for programmers and compilers alike, yielding worse performance and semantics than simply using structures directly.
The biggest principles to bear in mind when using structures are:
Don't pass or return structures by value or otherwise cause them to be copied unnecessarily.
If principle #1 is adhered to, large structures will perform just as well as small ones.
If Alphablob
is a structure containing 26 public int
fields named a-z, and a property getter ab
which returns the sum of its a
and b
fields, then given Alphablob[] arr; List<Alphablob> list;
, the code int foo = arr[0].ab + list[0].ab;
will need to read fields a
and b
of arr[0]
, but will need to read all 26 fields of list[0]
even though it will ignore all but two of them. If one wanted to have a generic list-like collection that could work efficiently with a structure like alphaBlob
, one should replace the indexed getter with a method:
delegate ActByRef<T1,T2>(ref T1 p1, ref T2 p2);
actOnItem<TParam>(int index, ActByRef<T, TParam> proc, ref TParam param);
which would then invoke proc(ref backingArray[index], ref param);
. Given such a collection, if one replaces sum = myCollection[0].ab;
with
int result;
myCollection.actOnItem<int>(0,
ref (ref alphaBlob item, ref int dest)=>dest = item,
ref result);
that would avoid the need to copy portions of the alphaBlob
that aren't going to be used in the property getter. Since the passed delegate doesn't access anything other than its ref
parameters, the compiler can pass a static delegate.
Unfortunately, the .NET Framework doesn't define any of the kinds of delegates needed to make this thing work nicely, and the syntax ends up being kind of a mess. On the other hand, this approach makes it possible to avoid copying structures needlessly, which will in turn make it practical to perform in-place actions on large structures stored within arrays, which is the most efficient way of accessing storage.
$endgroup$
$begingroup$
Hi, did you post your answer to the wrong page?
$endgroup$
– piojo
Aug 16 at 16:56
$begingroup$
@pojo: Perhaps I should have made clearer that the purpose of the answer is to identify a situation where using properties rather than fields is bad, and identify how one can achieve the performance and semantic advantages of fields, while still encapsulating access.
$endgroup$
– supercat
Aug 16 at 17:42
$begingroup$
@piojo: Does my edit make things clearer?
$endgroup$
– supercat
Aug 16 at 17:55
$begingroup$
"will need to read all 26 fields of list[0] even though it will ignore all but two of them." what? Are you sure? Have you checked the MSIL? C# nearly always passes class types by reference.
$endgroup$
– pjc50
Aug 16 at 20:23
$begingroup$
@pjc50: Reading a property yields a result by value. If both the indexed getter forlist
and the property getter forab
are both in-lined, it might be possible for a JITter to recognize that only membersa
andb
are needed, but I'm unaware of any JITter version actually doing such things.
$endgroup$
– supercat
Aug 16 at 21:27
|
show 8 more comments
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "53"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgamedev.stackexchange.com%2fquestions%2f174659%2fis-the-microsoft-recommendation-to-use-c-properties-applicable-to-game-developm%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
Not necessarily. Just like in application software, there is code in a game which is performance-critical and code which is not.
If the code is executed several thousand times per frame, then such a low-level optimization might make sense. (Although you might first want to check first if it is actually necessary to call it that often. The fastest code is code you don't run)
If the code is executed once every couple seconds, then readability and maintainability is far more important than performance.
I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
With trivial properties in the style of int Foo get; private set;
you can be pretty certain that the compiler will optimize the property wrapper away. But:
- if you actually have an implementation, then you can not be that sure anymore. The more complex that implementation, the less likely that the compiler will be able to inline it.
- Properties can hide complexity. This is a double-edged sword. On the one hand, it makes your code more readable and changeable. But on the other hand, another developer who accesses a property of your class might think they are just accessing a single variable and not realize how much code you've actually hidden behind that property. When a property starts to become computationally expensive, then I tend to refactor it into an explicit
GetFoo()
/SetFoo(value)
method: To imply that there is a lot more happening behind the scenes. (or if I need to be even more sure that others get the hint:CalculateFoo()
/SwitchFoo(value)
)
$endgroup$
$begingroup$
Accessing a field within a non-read-only public field of structure type is fast, even if that field is within a structure that is within a structure etc., provided that the top-level object is either a non-read-only class field or a non-read-only free-standing variable. Structures can be quite large without adversely affecting performance if these conditions apply. Breaking this pattern will cause slowdown proportional to structure size.
$endgroup$
– supercat
Aug 15 at 20:06
5
$begingroup$
"then I tend to refactor it into an explicit GetFoo() / SetFoo(value) method:" - Good point, I tend to move heavy operations out of properties into methods.
$endgroup$
– Mark Rogers
Aug 15 at 20:53
$begingroup$
Is there a way to confirm that the Unity 3D compiler makes the optimization you mention (in IL2CPP and Mono builds for Android)?
$endgroup$
– piojo
Aug 16 at 5:02
9
$begingroup$
@piojo As with most performance questions, the simplest answer is "just do it". You have the code ready - test the difference between having a field and having a property. The implementation details are only worth investigating when you can actually measure an important difference between the two approaches. In my experience, if you write everything to be as fast as possible, you limit the available high level optimizations, and just try to race the low level parts ("can't see forest for the trees"). E.g. finding ways to skipUpdate
entirely will save you more time than makingUpdate
fast.
$endgroup$
– Luaan
Aug 16 at 8:16
add a comment |
$begingroup$
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
Not necessarily. Just like in application software, there is code in a game which is performance-critical and code which is not.
If the code is executed several thousand times per frame, then such a low-level optimization might make sense. (Although you might first want to check first if it is actually necessary to call it that often. The fastest code is code you don't run)
If the code is executed once every couple seconds, then readability and maintainability is far more important than performance.
I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
With trivial properties in the style of int Foo get; private set;
you can be pretty certain that the compiler will optimize the property wrapper away. But:
- if you actually have an implementation, then you can not be that sure anymore. The more complex that implementation, the less likely that the compiler will be able to inline it.
- Properties can hide complexity. This is a double-edged sword. On the one hand, it makes your code more readable and changeable. But on the other hand, another developer who accesses a property of your class might think they are just accessing a single variable and not realize how much code you've actually hidden behind that property. When a property starts to become computationally expensive, then I tend to refactor it into an explicit
GetFoo()
/SetFoo(value)
method: To imply that there is a lot more happening behind the scenes. (or if I need to be even more sure that others get the hint:CalculateFoo()
/SwitchFoo(value)
)
$endgroup$
$begingroup$
Accessing a field within a non-read-only public field of structure type is fast, even if that field is within a structure that is within a structure etc., provided that the top-level object is either a non-read-only class field or a non-read-only free-standing variable. Structures can be quite large without adversely affecting performance if these conditions apply. Breaking this pattern will cause slowdown proportional to structure size.
$endgroup$
– supercat
Aug 15 at 20:06
5
$begingroup$
"then I tend to refactor it into an explicit GetFoo() / SetFoo(value) method:" - Good point, I tend to move heavy operations out of properties into methods.
$endgroup$
– Mark Rogers
Aug 15 at 20:53
$begingroup$
Is there a way to confirm that the Unity 3D compiler makes the optimization you mention (in IL2CPP and Mono builds for Android)?
$endgroup$
– piojo
Aug 16 at 5:02
9
$begingroup$
@piojo As with most performance questions, the simplest answer is "just do it". You have the code ready - test the difference between having a field and having a property. The implementation details are only worth investigating when you can actually measure an important difference between the two approaches. In my experience, if you write everything to be as fast as possible, you limit the available high level optimizations, and just try to race the low level parts ("can't see forest for the trees"). E.g. finding ways to skipUpdate
entirely will save you more time than makingUpdate
fast.
$endgroup$
– Luaan
Aug 16 at 8:16
add a comment |
$begingroup$
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
Not necessarily. Just like in application software, there is code in a game which is performance-critical and code which is not.
If the code is executed several thousand times per frame, then such a low-level optimization might make sense. (Although you might first want to check first if it is actually necessary to call it that often. The fastest code is code you don't run)
If the code is executed once every couple seconds, then readability and maintainability is far more important than performance.
I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
With trivial properties in the style of int Foo get; private set;
you can be pretty certain that the compiler will optimize the property wrapper away. But:
- if you actually have an implementation, then you can not be that sure anymore. The more complex that implementation, the less likely that the compiler will be able to inline it.
- Properties can hide complexity. This is a double-edged sword. On the one hand, it makes your code more readable and changeable. But on the other hand, another developer who accesses a property of your class might think they are just accessing a single variable and not realize how much code you've actually hidden behind that property. When a property starts to become computationally expensive, then I tend to refactor it into an explicit
GetFoo()
/SetFoo(value)
method: To imply that there is a lot more happening behind the scenes. (or if I need to be even more sure that others get the hint:CalculateFoo()
/SwitchFoo(value)
)
$endgroup$
But my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
Not necessarily. Just like in application software, there is code in a game which is performance-critical and code which is not.
If the code is executed several thousand times per frame, then such a low-level optimization might make sense. (Although you might first want to check first if it is actually necessary to call it that often. The fastest code is code you don't run)
If the code is executed once every couple seconds, then readability and maintainability is far more important than performance.
I've read is that Unity 3D is not sure to inline access via properties, so using a property will result in an extra function call.
With trivial properties in the style of int Foo get; private set;
you can be pretty certain that the compiler will optimize the property wrapper away. But:
- if you actually have an implementation, then you can not be that sure anymore. The more complex that implementation, the less likely that the compiler will be able to inline it.
- Properties can hide complexity. This is a double-edged sword. On the one hand, it makes your code more readable and changeable. But on the other hand, another developer who accesses a property of your class might think they are just accessing a single variable and not realize how much code you've actually hidden behind that property. When a property starts to become computationally expensive, then I tend to refactor it into an explicit
GetFoo()
/SetFoo(value)
method: To imply that there is a lot more happening behind the scenes. (or if I need to be even more sure that others get the hint:CalculateFoo()
/SwitchFoo(value)
)
edited Aug 16 at 8:23
answered Aug 15 at 8:00
PhilippPhilipp
86.7k20 gold badges201 silver badges256 bronze badges
86.7k20 gold badges201 silver badges256 bronze badges
$begingroup$
Accessing a field within a non-read-only public field of structure type is fast, even if that field is within a structure that is within a structure etc., provided that the top-level object is either a non-read-only class field or a non-read-only free-standing variable. Structures can be quite large without adversely affecting performance if these conditions apply. Breaking this pattern will cause slowdown proportional to structure size.
$endgroup$
– supercat
Aug 15 at 20:06
5
$begingroup$
"then I tend to refactor it into an explicit GetFoo() / SetFoo(value) method:" - Good point, I tend to move heavy operations out of properties into methods.
$endgroup$
– Mark Rogers
Aug 15 at 20:53
$begingroup$
Is there a way to confirm that the Unity 3D compiler makes the optimization you mention (in IL2CPP and Mono builds for Android)?
$endgroup$
– piojo
Aug 16 at 5:02
9
$begingroup$
@piojo As with most performance questions, the simplest answer is "just do it". You have the code ready - test the difference between having a field and having a property. The implementation details are only worth investigating when you can actually measure an important difference between the two approaches. In my experience, if you write everything to be as fast as possible, you limit the available high level optimizations, and just try to race the low level parts ("can't see forest for the trees"). E.g. finding ways to skipUpdate
entirely will save you more time than makingUpdate
fast.
$endgroup$
– Luaan
Aug 16 at 8:16
add a comment |
$begingroup$
Accessing a field within a non-read-only public field of structure type is fast, even if that field is within a structure that is within a structure etc., provided that the top-level object is either a non-read-only class field or a non-read-only free-standing variable. Structures can be quite large without adversely affecting performance if these conditions apply. Breaking this pattern will cause slowdown proportional to structure size.
$endgroup$
– supercat
Aug 15 at 20:06
5
$begingroup$
"then I tend to refactor it into an explicit GetFoo() / SetFoo(value) method:" - Good point, I tend to move heavy operations out of properties into methods.
$endgroup$
– Mark Rogers
Aug 15 at 20:53
$begingroup$
Is there a way to confirm that the Unity 3D compiler makes the optimization you mention (in IL2CPP and Mono builds for Android)?
$endgroup$
– piojo
Aug 16 at 5:02
9
$begingroup$
@piojo As with most performance questions, the simplest answer is "just do it". You have the code ready - test the difference between having a field and having a property. The implementation details are only worth investigating when you can actually measure an important difference between the two approaches. In my experience, if you write everything to be as fast as possible, you limit the available high level optimizations, and just try to race the low level parts ("can't see forest for the trees"). E.g. finding ways to skipUpdate
entirely will save you more time than makingUpdate
fast.
$endgroup$
– Luaan
Aug 16 at 8:16
$begingroup$
Accessing a field within a non-read-only public field of structure type is fast, even if that field is within a structure that is within a structure etc., provided that the top-level object is either a non-read-only class field or a non-read-only free-standing variable. Structures can be quite large without adversely affecting performance if these conditions apply. Breaking this pattern will cause slowdown proportional to structure size.
$endgroup$
– supercat
Aug 15 at 20:06
$begingroup$
Accessing a field within a non-read-only public field of structure type is fast, even if that field is within a structure that is within a structure etc., provided that the top-level object is either a non-read-only class field or a non-read-only free-standing variable. Structures can be quite large without adversely affecting performance if these conditions apply. Breaking this pattern will cause slowdown proportional to structure size.
$endgroup$
– supercat
Aug 15 at 20:06
5
5
$begingroup$
"then I tend to refactor it into an explicit GetFoo() / SetFoo(value) method:" - Good point, I tend to move heavy operations out of properties into methods.
$endgroup$
– Mark Rogers
Aug 15 at 20:53
$begingroup$
"then I tend to refactor it into an explicit GetFoo() / SetFoo(value) method:" - Good point, I tend to move heavy operations out of properties into methods.
$endgroup$
– Mark Rogers
Aug 15 at 20:53
$begingroup$
Is there a way to confirm that the Unity 3D compiler makes the optimization you mention (in IL2CPP and Mono builds for Android)?
$endgroup$
– piojo
Aug 16 at 5:02
$begingroup$
Is there a way to confirm that the Unity 3D compiler makes the optimization you mention (in IL2CPP and Mono builds for Android)?
$endgroup$
– piojo
Aug 16 at 5:02
9
9
$begingroup$
@piojo As with most performance questions, the simplest answer is "just do it". You have the code ready - test the difference between having a field and having a property. The implementation details are only worth investigating when you can actually measure an important difference between the two approaches. In my experience, if you write everything to be as fast as possible, you limit the available high level optimizations, and just try to race the low level parts ("can't see forest for the trees"). E.g. finding ways to skip
Update
entirely will save you more time than making Update
fast.$endgroup$
– Luaan
Aug 16 at 8:16
$begingroup$
@piojo As with most performance questions, the simplest answer is "just do it". You have the code ready - test the difference between having a field and having a property. The implementation details are only worth investigating when you can actually measure an important difference between the two approaches. In my experience, if you write everything to be as fast as possible, you limit the available high level optimizations, and just try to race the low level parts ("can't see forest for the trees"). E.g. finding ways to skip
Update
entirely will save you more time than making Update
fast.$endgroup$
– Luaan
Aug 16 at 8:16
add a comment |
$begingroup$
When in doubt, use best practices.
You are in doubt.
That was the easy answer. Reality is more complex, of course.
First, there's the myth that game programming is ultra super high performance programming and everything has to be as fast as possible. I classify game programming as performance aware programming. The developer must be aware of performance constraints and work within them.
Second, there's the myth that making every single thing as fast as possible is what makes a program run fast. In reality, identifying and optimizing bottlenecks is what makes a program fast, and that is much easier/cheaper/faster to do if the code easy to maintain and modify; extremely optimized code is hard to maintain and modify. It follows that in order to write extremely optimized programs, you have to use extreme code optimization as often as needed and as rarely as possible.
Third, the benefit of properties and accessors is that they are robust to change, and thus make code easier to maintain and modify - which is something you need to write fast programs. Want to throw an exception whenever someone wants to set your value to null? Use a setter. Want to send a notification whenever the value changes? Use a setter. Want to log the new value? Use a setter. Want to do lazy initialization? Use a getter.
And fourth, personally I don't follow Microsoft's best practice in this instance. If I need a property with trivial and public getters and setters, I just use a field, and simply change it to a property when I need to. However, I very rarely need such a trivial property - it's far more common that I want to check for boundary conditions, or want to make the setter private.
$endgroup$
add a comment |
$begingroup$
When in doubt, use best practices.
You are in doubt.
That was the easy answer. Reality is more complex, of course.
First, there's the myth that game programming is ultra super high performance programming and everything has to be as fast as possible. I classify game programming as performance aware programming. The developer must be aware of performance constraints and work within them.
Second, there's the myth that making every single thing as fast as possible is what makes a program run fast. In reality, identifying and optimizing bottlenecks is what makes a program fast, and that is much easier/cheaper/faster to do if the code easy to maintain and modify; extremely optimized code is hard to maintain and modify. It follows that in order to write extremely optimized programs, you have to use extreme code optimization as often as needed and as rarely as possible.
Third, the benefit of properties and accessors is that they are robust to change, and thus make code easier to maintain and modify - which is something you need to write fast programs. Want to throw an exception whenever someone wants to set your value to null? Use a setter. Want to send a notification whenever the value changes? Use a setter. Want to log the new value? Use a setter. Want to do lazy initialization? Use a getter.
And fourth, personally I don't follow Microsoft's best practice in this instance. If I need a property with trivial and public getters and setters, I just use a field, and simply change it to a property when I need to. However, I very rarely need such a trivial property - it's far more common that I want to check for boundary conditions, or want to make the setter private.
$endgroup$
add a comment |
$begingroup$
When in doubt, use best practices.
You are in doubt.
That was the easy answer. Reality is more complex, of course.
First, there's the myth that game programming is ultra super high performance programming and everything has to be as fast as possible. I classify game programming as performance aware programming. The developer must be aware of performance constraints and work within them.
Second, there's the myth that making every single thing as fast as possible is what makes a program run fast. In reality, identifying and optimizing bottlenecks is what makes a program fast, and that is much easier/cheaper/faster to do if the code easy to maintain and modify; extremely optimized code is hard to maintain and modify. It follows that in order to write extremely optimized programs, you have to use extreme code optimization as often as needed and as rarely as possible.
Third, the benefit of properties and accessors is that they are robust to change, and thus make code easier to maintain and modify - which is something you need to write fast programs. Want to throw an exception whenever someone wants to set your value to null? Use a setter. Want to send a notification whenever the value changes? Use a setter. Want to log the new value? Use a setter. Want to do lazy initialization? Use a getter.
And fourth, personally I don't follow Microsoft's best practice in this instance. If I need a property with trivial and public getters and setters, I just use a field, and simply change it to a property when I need to. However, I very rarely need such a trivial property - it's far more common that I want to check for boundary conditions, or want to make the setter private.
$endgroup$
When in doubt, use best practices.
You are in doubt.
That was the easy answer. Reality is more complex, of course.
First, there's the myth that game programming is ultra super high performance programming and everything has to be as fast as possible. I classify game programming as performance aware programming. The developer must be aware of performance constraints and work within them.
Second, there's the myth that making every single thing as fast as possible is what makes a program run fast. In reality, identifying and optimizing bottlenecks is what makes a program fast, and that is much easier/cheaper/faster to do if the code easy to maintain and modify; extremely optimized code is hard to maintain and modify. It follows that in order to write extremely optimized programs, you have to use extreme code optimization as often as needed and as rarely as possible.
Third, the benefit of properties and accessors is that they are robust to change, and thus make code easier to maintain and modify - which is something you need to write fast programs. Want to throw an exception whenever someone wants to set your value to null? Use a setter. Want to send a notification whenever the value changes? Use a setter. Want to log the new value? Use a setter. Want to do lazy initialization? Use a getter.
And fourth, personally I don't follow Microsoft's best practice in this instance. If I need a property with trivial and public getters and setters, I just use a field, and simply change it to a property when I need to. However, I very rarely need such a trivial property - it's far more common that I want to check for boundary conditions, or want to make the setter private.
edited Aug 16 at 22:31
answered Aug 16 at 14:33
PeterPeter
9,3501 gold badge24 silver badges42 bronze badges
9,3501 gold badge24 silver badges42 bronze badges
add a comment |
add a comment |
$begingroup$
It is very easy for the .net runtime to inline simple properties, and often it does. But, this inlining is normally disabled by profilers, hence it is easy to be misled and think that changing a public property to a public field will speed up software.
In code that is called by other code that will not be recompiled when your code is recompiled there is a good case for using properties, as changing from a field to a property is a breaking change. But for most code, other than being able to set a breakpoint on the get/set, I have never seen benefits in using a simple property compared to a public field.
The primary reason I used properties in my 10 years as a professional C# programmer was to stop other programmers telling me I was not keeping to the coding standard. This was a good tradeoff, as hardly ever was there a good reason not to use a property.
$endgroup$
add a comment |
$begingroup$
It is very easy for the .net runtime to inline simple properties, and often it does. But, this inlining is normally disabled by profilers, hence it is easy to be misled and think that changing a public property to a public field will speed up software.
In code that is called by other code that will not be recompiled when your code is recompiled there is a good case for using properties, as changing from a field to a property is a breaking change. But for most code, other than being able to set a breakpoint on the get/set, I have never seen benefits in using a simple property compared to a public field.
The primary reason I used properties in my 10 years as a professional C# programmer was to stop other programmers telling me I was not keeping to the coding standard. This was a good tradeoff, as hardly ever was there a good reason not to use a property.
$endgroup$
add a comment |
$begingroup$
It is very easy for the .net runtime to inline simple properties, and often it does. But, this inlining is normally disabled by profilers, hence it is easy to be misled and think that changing a public property to a public field will speed up software.
In code that is called by other code that will not be recompiled when your code is recompiled there is a good case for using properties, as changing from a field to a property is a breaking change. But for most code, other than being able to set a breakpoint on the get/set, I have never seen benefits in using a simple property compared to a public field.
The primary reason I used properties in my 10 years as a professional C# programmer was to stop other programmers telling me I was not keeping to the coding standard. This was a good tradeoff, as hardly ever was there a good reason not to use a property.
$endgroup$
It is very easy for the .net runtime to inline simple properties, and often it does. But, this inlining is normally disabled by profilers, hence it is easy to be misled and think that changing a public property to a public field will speed up software.
In code that is called by other code that will not be recompiled when your code is recompiled there is a good case for using properties, as changing from a field to a property is a breaking change. But for most code, other than being able to set a breakpoint on the get/set, I have never seen benefits in using a simple property compared to a public field.
The primary reason I used properties in my 10 years as a professional C# programmer was to stop other programmers telling me I was not keeping to the coding standard. This was a good tradeoff, as hardly ever was there a good reason not to use a property.
answered Aug 16 at 13:19
Ian RingroseIan Ringrose
1213 bronze badges
1213 bronze badges
add a comment |
add a comment |
$begingroup$
Structs and naked fields will ease interoperability with some not managed APIs. Often you will find that the low level API wants to access the values by reference, which is good for performance (as we avoid an unnecessary copy). Using properties is an obstacle to that, and often times the wrapper libraries will do copies for ease of use, and sometimes for security.
Because of that, you will often get better performance having vector and matrix types that do not have properties but naked fields.
Best practices are not creating in vaccum. Despite some cargo cult, in general best practices are there for a good reason.
In this case, we have a couple:
A property allows you to change the implementation without changing the client code (on a binary level, it is possible to change a field to a property without changing the client code on a source level, however it will compile to something different after the change). That means, that by using a property from the start, the code that references yours will not have to be recompiled just to change what the property does internally.
If not all the possible values of the fields of your type are valid states, then you do not want to expose them to client code that code modify it. Thus, if some combinations of values are invalid, you want to keep the fields private (or internal).
I have been saying client code. That means code that calls into yours. If you are not making a library (or even making library but using internal instead of public), you can usually get away with it and some good discipline. In that situation the best practice of using properties is there to prevent you from shooting yourself in the foot. Furthermore, it is much easier to reason about code if you can see all the places where a field can change in a single file, instead of having to worry on whatever or not it is being modified somewhere else. In fact, properties are also good to put breakpoints when you are figuring out what went wrong.
Yes, there is value is seeing what is being done int industry. However, do you have a motivation to go against the best practices? or are you just going against the best practices – making the code harder to reason about – just because somebody else did it? Ah, by the way, "others do it" is how you start a cargo cult.
So... Is your game running slow? You are better of devoting time to figure out the bottleneck and fixing that, instead of speculating what could it be. You can rest assured that the compiler will do plenty of optimizations, because of that, chances are you are looking at the wrong problem.
On the flip side, if you are deciding what to do to begin with, you should worry about what algorithms and data structures first, instead of worrying about smaller details such as fields vs properties.
Finally, do you earn something by going against best practices?
For the particulars of you case (Unity and Mono for Android), does Unity takes values by reference? If it doesn't, it will copy the values anyway, no performance gain there.
If it does, if you are passing this data to an API that takes ref. Does it make sense to make the field public, or you could make the type able to call the API directly?
Yes, of course, there could be optimizations that you could do by using structs with naked fields. For example, you access them with pointers Span<T>
, or similar. They are also compact on memory, making them easy to serialize to send over the network or put in permanent storage (and yes those are copies).
Now, have you picked the right algorithms and structures, if they turn out to be a bottleneck, then you decide what is the best way to fix it... that could be structs with naked fields or not. You will be able to worry about that if and when it happens. Meanwhile you can worry about more important matters such as making a good or fun game worth playing.
$endgroup$
add a comment |
$begingroup$
Structs and naked fields will ease interoperability with some not managed APIs. Often you will find that the low level API wants to access the values by reference, which is good for performance (as we avoid an unnecessary copy). Using properties is an obstacle to that, and often times the wrapper libraries will do copies for ease of use, and sometimes for security.
Because of that, you will often get better performance having vector and matrix types that do not have properties but naked fields.
Best practices are not creating in vaccum. Despite some cargo cult, in general best practices are there for a good reason.
In this case, we have a couple:
A property allows you to change the implementation without changing the client code (on a binary level, it is possible to change a field to a property without changing the client code on a source level, however it will compile to something different after the change). That means, that by using a property from the start, the code that references yours will not have to be recompiled just to change what the property does internally.
If not all the possible values of the fields of your type are valid states, then you do not want to expose them to client code that code modify it. Thus, if some combinations of values are invalid, you want to keep the fields private (or internal).
I have been saying client code. That means code that calls into yours. If you are not making a library (or even making library but using internal instead of public), you can usually get away with it and some good discipline. In that situation the best practice of using properties is there to prevent you from shooting yourself in the foot. Furthermore, it is much easier to reason about code if you can see all the places where a field can change in a single file, instead of having to worry on whatever or not it is being modified somewhere else. In fact, properties are also good to put breakpoints when you are figuring out what went wrong.
Yes, there is value is seeing what is being done int industry. However, do you have a motivation to go against the best practices? or are you just going against the best practices – making the code harder to reason about – just because somebody else did it? Ah, by the way, "others do it" is how you start a cargo cult.
So... Is your game running slow? You are better of devoting time to figure out the bottleneck and fixing that, instead of speculating what could it be. You can rest assured that the compiler will do plenty of optimizations, because of that, chances are you are looking at the wrong problem.
On the flip side, if you are deciding what to do to begin with, you should worry about what algorithms and data structures first, instead of worrying about smaller details such as fields vs properties.
Finally, do you earn something by going against best practices?
For the particulars of you case (Unity and Mono for Android), does Unity takes values by reference? If it doesn't, it will copy the values anyway, no performance gain there.
If it does, if you are passing this data to an API that takes ref. Does it make sense to make the field public, or you could make the type able to call the API directly?
Yes, of course, there could be optimizations that you could do by using structs with naked fields. For example, you access them with pointers Span<T>
, or similar. They are also compact on memory, making them easy to serialize to send over the network or put in permanent storage (and yes those are copies).
Now, have you picked the right algorithms and structures, if they turn out to be a bottleneck, then you decide what is the best way to fix it... that could be structs with naked fields or not. You will be able to worry about that if and when it happens. Meanwhile you can worry about more important matters such as making a good or fun game worth playing.
$endgroup$
add a comment |
$begingroup$
Structs and naked fields will ease interoperability with some not managed APIs. Often you will find that the low level API wants to access the values by reference, which is good for performance (as we avoid an unnecessary copy). Using properties is an obstacle to that, and often times the wrapper libraries will do copies for ease of use, and sometimes for security.
Because of that, you will often get better performance having vector and matrix types that do not have properties but naked fields.
Best practices are not creating in vaccum. Despite some cargo cult, in general best practices are there for a good reason.
In this case, we have a couple:
A property allows you to change the implementation without changing the client code (on a binary level, it is possible to change a field to a property without changing the client code on a source level, however it will compile to something different after the change). That means, that by using a property from the start, the code that references yours will not have to be recompiled just to change what the property does internally.
If not all the possible values of the fields of your type are valid states, then you do not want to expose them to client code that code modify it. Thus, if some combinations of values are invalid, you want to keep the fields private (or internal).
I have been saying client code. That means code that calls into yours. If you are not making a library (or even making library but using internal instead of public), you can usually get away with it and some good discipline. In that situation the best practice of using properties is there to prevent you from shooting yourself in the foot. Furthermore, it is much easier to reason about code if you can see all the places where a field can change in a single file, instead of having to worry on whatever or not it is being modified somewhere else. In fact, properties are also good to put breakpoints when you are figuring out what went wrong.
Yes, there is value is seeing what is being done int industry. However, do you have a motivation to go against the best practices? or are you just going against the best practices – making the code harder to reason about – just because somebody else did it? Ah, by the way, "others do it" is how you start a cargo cult.
So... Is your game running slow? You are better of devoting time to figure out the bottleneck and fixing that, instead of speculating what could it be. You can rest assured that the compiler will do plenty of optimizations, because of that, chances are you are looking at the wrong problem.
On the flip side, if you are deciding what to do to begin with, you should worry about what algorithms and data structures first, instead of worrying about smaller details such as fields vs properties.
Finally, do you earn something by going against best practices?
For the particulars of you case (Unity and Mono for Android), does Unity takes values by reference? If it doesn't, it will copy the values anyway, no performance gain there.
If it does, if you are passing this data to an API that takes ref. Does it make sense to make the field public, or you could make the type able to call the API directly?
Yes, of course, there could be optimizations that you could do by using structs with naked fields. For example, you access them with pointers Span<T>
, or similar. They are also compact on memory, making them easy to serialize to send over the network or put in permanent storage (and yes those are copies).
Now, have you picked the right algorithms and structures, if they turn out to be a bottleneck, then you decide what is the best way to fix it... that could be structs with naked fields or not. You will be able to worry about that if and when it happens. Meanwhile you can worry about more important matters such as making a good or fun game worth playing.
$endgroup$
Structs and naked fields will ease interoperability with some not managed APIs. Often you will find that the low level API wants to access the values by reference, which is good for performance (as we avoid an unnecessary copy). Using properties is an obstacle to that, and often times the wrapper libraries will do copies for ease of use, and sometimes for security.
Because of that, you will often get better performance having vector and matrix types that do not have properties but naked fields.
Best practices are not creating in vaccum. Despite some cargo cult, in general best practices are there for a good reason.
In this case, we have a couple:
A property allows you to change the implementation without changing the client code (on a binary level, it is possible to change a field to a property without changing the client code on a source level, however it will compile to something different after the change). That means, that by using a property from the start, the code that references yours will not have to be recompiled just to change what the property does internally.
If not all the possible values of the fields of your type are valid states, then you do not want to expose them to client code that code modify it. Thus, if some combinations of values are invalid, you want to keep the fields private (or internal).
I have been saying client code. That means code that calls into yours. If you are not making a library (or even making library but using internal instead of public), you can usually get away with it and some good discipline. In that situation the best practice of using properties is there to prevent you from shooting yourself in the foot. Furthermore, it is much easier to reason about code if you can see all the places where a field can change in a single file, instead of having to worry on whatever or not it is being modified somewhere else. In fact, properties are also good to put breakpoints when you are figuring out what went wrong.
Yes, there is value is seeing what is being done int industry. However, do you have a motivation to go against the best practices? or are you just going against the best practices – making the code harder to reason about – just because somebody else did it? Ah, by the way, "others do it" is how you start a cargo cult.
So... Is your game running slow? You are better of devoting time to figure out the bottleneck and fixing that, instead of speculating what could it be. You can rest assured that the compiler will do plenty of optimizations, because of that, chances are you are looking at the wrong problem.
On the flip side, if you are deciding what to do to begin with, you should worry about what algorithms and data structures first, instead of worrying about smaller details such as fields vs properties.
Finally, do you earn something by going against best practices?
For the particulars of you case (Unity and Mono for Android), does Unity takes values by reference? If it doesn't, it will copy the values anyway, no performance gain there.
If it does, if you are passing this data to an API that takes ref. Does it make sense to make the field public, or you could make the type able to call the API directly?
Yes, of course, there could be optimizations that you could do by using structs with naked fields. For example, you access them with pointers Span<T>
, or similar. They are also compact on memory, making them easy to serialize to send over the network or put in permanent storage (and yes those are copies).
Now, have you picked the right algorithms and structures, if they turn out to be a bottleneck, then you decide what is the best way to fix it... that could be structs with naked fields or not. You will be able to worry about that if and when it happens. Meanwhile you can worry about more important matters such as making a good or fun game worth playing.
answered Aug 16 at 18:27
TheraotTheraot
8,1573 gold badges20 silver badges29 bronze badges
8,1573 gold badges20 silver badges29 bronze badges
add a comment |
add a comment |
$begingroup$
...my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
:
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
You are right to be aware that premature optimisation is bad but that is only half the story (see the full quote below). Even in game development, not everything needs to be as fast as possible.
First make it work. Only then, optimise the bits that need it. That's not to say that the first draft can be messy or needlessly inefficient but that optimisation is not a priority at this stage.
"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming." Donald Knuth, 1974.
$endgroup$
add a comment |
$begingroup$
...my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
:
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
You are right to be aware that premature optimisation is bad but that is only half the story (see the full quote below). Even in game development, not everything needs to be as fast as possible.
First make it work. Only then, optimise the bits that need it. That's not to say that the first draft can be messy or needlessly inefficient but that optimisation is not a priority at this stage.
"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming." Donald Knuth, 1974.
$endgroup$
add a comment |
$begingroup$
...my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
:
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
You are right to be aware that premature optimisation is bad but that is only half the story (see the full quote below). Even in game development, not everything needs to be as fast as possible.
First make it work. Only then, optimise the bits that need it. That's not to say that the first draft can be messy or needlessly inefficient but that optimisation is not a priority at this stage.
"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming." Donald Knuth, 1974.
$endgroup$
...my impression is that in game development, unless you have a reason to do otherwise, everything should be nearly as fast as possible.
:
I'm aware that premature optimization is bad, but as I said, in game development you don't make something slow when a similar effort could make it fast.
You are right to be aware that premature optimisation is bad but that is only half the story (see the full quote below). Even in game development, not everything needs to be as fast as possible.
First make it work. Only then, optimise the bits that need it. That's not to say that the first draft can be messy or needlessly inefficient but that optimisation is not a priority at this stage.
"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming." Donald Knuth, 1974.
answered Aug 16 at 13:35
Vincent O'SullivanVincent O'Sullivan
111 bronze badge
111 bronze badge
add a comment |
add a comment |
$begingroup$
For basic stuff like that, the C# optimizer's going to get it right anyway. If you worry about it (and if you worry about it for more than 1% of your code, you're doing it wrong) an attribute was created for you. The attribute [MethodImpl(MethodImplOptions.AggressiveInlining)]
greatly increases the chance a method will be inlined (property getters and setters are methods).
$endgroup$
add a comment |
$begingroup$
For basic stuff like that, the C# optimizer's going to get it right anyway. If you worry about it (and if you worry about it for more than 1% of your code, you're doing it wrong) an attribute was created for you. The attribute [MethodImpl(MethodImplOptions.AggressiveInlining)]
greatly increases the chance a method will be inlined (property getters and setters are methods).
$endgroup$
add a comment |
$begingroup$
For basic stuff like that, the C# optimizer's going to get it right anyway. If you worry about it (and if you worry about it for more than 1% of your code, you're doing it wrong) an attribute was created for you. The attribute [MethodImpl(MethodImplOptions.AggressiveInlining)]
greatly increases the chance a method will be inlined (property getters and setters are methods).
$endgroup$
For basic stuff like that, the C# optimizer's going to get it right anyway. If you worry about it (and if you worry about it for more than 1% of your code, you're doing it wrong) an attribute was created for you. The attribute [MethodImpl(MethodImplOptions.AggressiveInlining)]
greatly increases the chance a method will be inlined (property getters and setters are methods).
answered Aug 17 at 20:58
JoshuaJoshua
1113 bronze badges
1113 bronze badges
add a comment |
add a comment |
$begingroup$
Exposing structure-type members as properties rather than fields will often yield poor performance and semantics, especially in cases where structures are actually treated as structures, rather than as "quirky objects".
A structure in .NET is a collection of fields duct-taped together, and which can for some purposes be treated as a unit. The .NET Framework is designed to allow structures to be used in much the same way as class objects, and there are times this can be convenient.
Much of the advice surrounding structures is predicated on the notion that programmers will be wanting to use structures as objects, rather than as taped-together collections of fields. On the other hand, there are many cases where it can be useful to have something that behaves as a taped-together bunch of fields. If that's what one needs, the .NET advice will add needless work for programmers and compilers alike, yielding worse performance and semantics than simply using structures directly.
The biggest principles to bear in mind when using structures are:
Don't pass or return structures by value or otherwise cause them to be copied unnecessarily.
If principle #1 is adhered to, large structures will perform just as well as small ones.
If Alphablob
is a structure containing 26 public int
fields named a-z, and a property getter ab
which returns the sum of its a
and b
fields, then given Alphablob[] arr; List<Alphablob> list;
, the code int foo = arr[0].ab + list[0].ab;
will need to read fields a
and b
of arr[0]
, but will need to read all 26 fields of list[0]
even though it will ignore all but two of them. If one wanted to have a generic list-like collection that could work efficiently with a structure like alphaBlob
, one should replace the indexed getter with a method:
delegate ActByRef<T1,T2>(ref T1 p1, ref T2 p2);
actOnItem<TParam>(int index, ActByRef<T, TParam> proc, ref TParam param);
which would then invoke proc(ref backingArray[index], ref param);
. Given such a collection, if one replaces sum = myCollection[0].ab;
with
int result;
myCollection.actOnItem<int>(0,
ref (ref alphaBlob item, ref int dest)=>dest = item,
ref result);
that would avoid the need to copy portions of the alphaBlob
that aren't going to be used in the property getter. Since the passed delegate doesn't access anything other than its ref
parameters, the compiler can pass a static delegate.
Unfortunately, the .NET Framework doesn't define any of the kinds of delegates needed to make this thing work nicely, and the syntax ends up being kind of a mess. On the other hand, this approach makes it possible to avoid copying structures needlessly, which will in turn make it practical to perform in-place actions on large structures stored within arrays, which is the most efficient way of accessing storage.
$endgroup$
$begingroup$
Hi, did you post your answer to the wrong page?
$endgroup$
– piojo
Aug 16 at 16:56
$begingroup$
@pojo: Perhaps I should have made clearer that the purpose of the answer is to identify a situation where using properties rather than fields is bad, and identify how one can achieve the performance and semantic advantages of fields, while still encapsulating access.
$endgroup$
– supercat
Aug 16 at 17:42
$begingroup$
@piojo: Does my edit make things clearer?
$endgroup$
– supercat
Aug 16 at 17:55
$begingroup$
"will need to read all 26 fields of list[0] even though it will ignore all but two of them." what? Are you sure? Have you checked the MSIL? C# nearly always passes class types by reference.
$endgroup$
– pjc50
Aug 16 at 20:23
$begingroup$
@pjc50: Reading a property yields a result by value. If both the indexed getter forlist
and the property getter forab
are both in-lined, it might be possible for a JITter to recognize that only membersa
andb
are needed, but I'm unaware of any JITter version actually doing such things.
$endgroup$
– supercat
Aug 16 at 21:27
|
show 8 more comments
$begingroup$
Exposing structure-type members as properties rather than fields will often yield poor performance and semantics, especially in cases where structures are actually treated as structures, rather than as "quirky objects".
A structure in .NET is a collection of fields duct-taped together, and which can for some purposes be treated as a unit. The .NET Framework is designed to allow structures to be used in much the same way as class objects, and there are times this can be convenient.
Much of the advice surrounding structures is predicated on the notion that programmers will be wanting to use structures as objects, rather than as taped-together collections of fields. On the other hand, there are many cases where it can be useful to have something that behaves as a taped-together bunch of fields. If that's what one needs, the .NET advice will add needless work for programmers and compilers alike, yielding worse performance and semantics than simply using structures directly.
The biggest principles to bear in mind when using structures are:
Don't pass or return structures by value or otherwise cause them to be copied unnecessarily.
If principle #1 is adhered to, large structures will perform just as well as small ones.
If Alphablob
is a structure containing 26 public int
fields named a-z, and a property getter ab
which returns the sum of its a
and b
fields, then given Alphablob[] arr; List<Alphablob> list;
, the code int foo = arr[0].ab + list[0].ab;
will need to read fields a
and b
of arr[0]
, but will need to read all 26 fields of list[0]
even though it will ignore all but two of them. If one wanted to have a generic list-like collection that could work efficiently with a structure like alphaBlob
, one should replace the indexed getter with a method:
delegate ActByRef<T1,T2>(ref T1 p1, ref T2 p2);
actOnItem<TParam>(int index, ActByRef<T, TParam> proc, ref TParam param);
which would then invoke proc(ref backingArray[index], ref param);
. Given such a collection, if one replaces sum = myCollection[0].ab;
with
int result;
myCollection.actOnItem<int>(0,
ref (ref alphaBlob item, ref int dest)=>dest = item,
ref result);
that would avoid the need to copy portions of the alphaBlob
that aren't going to be used in the property getter. Since the passed delegate doesn't access anything other than its ref
parameters, the compiler can pass a static delegate.
Unfortunately, the .NET Framework doesn't define any of the kinds of delegates needed to make this thing work nicely, and the syntax ends up being kind of a mess. On the other hand, this approach makes it possible to avoid copying structures needlessly, which will in turn make it practical to perform in-place actions on large structures stored within arrays, which is the most efficient way of accessing storage.
$endgroup$
$begingroup$
Hi, did you post your answer to the wrong page?
$endgroup$
– piojo
Aug 16 at 16:56
$begingroup$
@pojo: Perhaps I should have made clearer that the purpose of the answer is to identify a situation where using properties rather than fields is bad, and identify how one can achieve the performance and semantic advantages of fields, while still encapsulating access.
$endgroup$
– supercat
Aug 16 at 17:42
$begingroup$
@piojo: Does my edit make things clearer?
$endgroup$
– supercat
Aug 16 at 17:55
$begingroup$
"will need to read all 26 fields of list[0] even though it will ignore all but two of them." what? Are you sure? Have you checked the MSIL? C# nearly always passes class types by reference.
$endgroup$
– pjc50
Aug 16 at 20:23
$begingroup$
@pjc50: Reading a property yields a result by value. If both the indexed getter forlist
and the property getter forab
are both in-lined, it might be possible for a JITter to recognize that only membersa
andb
are needed, but I'm unaware of any JITter version actually doing such things.
$endgroup$
– supercat
Aug 16 at 21:27
|
show 8 more comments
$begingroup$
Exposing structure-type members as properties rather than fields will often yield poor performance and semantics, especially in cases where structures are actually treated as structures, rather than as "quirky objects".
A structure in .NET is a collection of fields duct-taped together, and which can for some purposes be treated as a unit. The .NET Framework is designed to allow structures to be used in much the same way as class objects, and there are times this can be convenient.
Much of the advice surrounding structures is predicated on the notion that programmers will be wanting to use structures as objects, rather than as taped-together collections of fields. On the other hand, there are many cases where it can be useful to have something that behaves as a taped-together bunch of fields. If that's what one needs, the .NET advice will add needless work for programmers and compilers alike, yielding worse performance and semantics than simply using structures directly.
The biggest principles to bear in mind when using structures are:
Don't pass or return structures by value or otherwise cause them to be copied unnecessarily.
If principle #1 is adhered to, large structures will perform just as well as small ones.
If Alphablob
is a structure containing 26 public int
fields named a-z, and a property getter ab
which returns the sum of its a
and b
fields, then given Alphablob[] arr; List<Alphablob> list;
, the code int foo = arr[0].ab + list[0].ab;
will need to read fields a
and b
of arr[0]
, but will need to read all 26 fields of list[0]
even though it will ignore all but two of them. If one wanted to have a generic list-like collection that could work efficiently with a structure like alphaBlob
, one should replace the indexed getter with a method:
delegate ActByRef<T1,T2>(ref T1 p1, ref T2 p2);
actOnItem<TParam>(int index, ActByRef<T, TParam> proc, ref TParam param);
which would then invoke proc(ref backingArray[index], ref param);
. Given such a collection, if one replaces sum = myCollection[0].ab;
with
int result;
myCollection.actOnItem<int>(0,
ref (ref alphaBlob item, ref int dest)=>dest = item,
ref result);
that would avoid the need to copy portions of the alphaBlob
that aren't going to be used in the property getter. Since the passed delegate doesn't access anything other than its ref
parameters, the compiler can pass a static delegate.
Unfortunately, the .NET Framework doesn't define any of the kinds of delegates needed to make this thing work nicely, and the syntax ends up being kind of a mess. On the other hand, this approach makes it possible to avoid copying structures needlessly, which will in turn make it practical to perform in-place actions on large structures stored within arrays, which is the most efficient way of accessing storage.
$endgroup$
Exposing structure-type members as properties rather than fields will often yield poor performance and semantics, especially in cases where structures are actually treated as structures, rather than as "quirky objects".
A structure in .NET is a collection of fields duct-taped together, and which can for some purposes be treated as a unit. The .NET Framework is designed to allow structures to be used in much the same way as class objects, and there are times this can be convenient.
Much of the advice surrounding structures is predicated on the notion that programmers will be wanting to use structures as objects, rather than as taped-together collections of fields. On the other hand, there are many cases where it can be useful to have something that behaves as a taped-together bunch of fields. If that's what one needs, the .NET advice will add needless work for programmers and compilers alike, yielding worse performance and semantics than simply using structures directly.
The biggest principles to bear in mind when using structures are:
Don't pass or return structures by value or otherwise cause them to be copied unnecessarily.
If principle #1 is adhered to, large structures will perform just as well as small ones.
If Alphablob
is a structure containing 26 public int
fields named a-z, and a property getter ab
which returns the sum of its a
and b
fields, then given Alphablob[] arr; List<Alphablob> list;
, the code int foo = arr[0].ab + list[0].ab;
will need to read fields a
and b
of arr[0]
, but will need to read all 26 fields of list[0]
even though it will ignore all but two of them. If one wanted to have a generic list-like collection that could work efficiently with a structure like alphaBlob
, one should replace the indexed getter with a method:
delegate ActByRef<T1,T2>(ref T1 p1, ref T2 p2);
actOnItem<TParam>(int index, ActByRef<T, TParam> proc, ref TParam param);
which would then invoke proc(ref backingArray[index], ref param);
. Given such a collection, if one replaces sum = myCollection[0].ab;
with
int result;
myCollection.actOnItem<int>(0,
ref (ref alphaBlob item, ref int dest)=>dest = item,
ref result);
that would avoid the need to copy portions of the alphaBlob
that aren't going to be used in the property getter. Since the passed delegate doesn't access anything other than its ref
parameters, the compiler can pass a static delegate.
Unfortunately, the .NET Framework doesn't define any of the kinds of delegates needed to make this thing work nicely, and the syntax ends up being kind of a mess. On the other hand, this approach makes it possible to avoid copying structures needlessly, which will in turn make it practical to perform in-place actions on large structures stored within arrays, which is the most efficient way of accessing storage.
edited Aug 16 at 17:54
answered Aug 16 at 16:54
supercatsupercat
4552 silver badges4 bronze badges
4552 silver badges4 bronze badges
$begingroup$
Hi, did you post your answer to the wrong page?
$endgroup$
– piojo
Aug 16 at 16:56
$begingroup$
@pojo: Perhaps I should have made clearer that the purpose of the answer is to identify a situation where using properties rather than fields is bad, and identify how one can achieve the performance and semantic advantages of fields, while still encapsulating access.
$endgroup$
– supercat
Aug 16 at 17:42
$begingroup$
@piojo: Does my edit make things clearer?
$endgroup$
– supercat
Aug 16 at 17:55
$begingroup$
"will need to read all 26 fields of list[0] even though it will ignore all but two of them." what? Are you sure? Have you checked the MSIL? C# nearly always passes class types by reference.
$endgroup$
– pjc50
Aug 16 at 20:23
$begingroup$
@pjc50: Reading a property yields a result by value. If both the indexed getter forlist
and the property getter forab
are both in-lined, it might be possible for a JITter to recognize that only membersa
andb
are needed, but I'm unaware of any JITter version actually doing such things.
$endgroup$
– supercat
Aug 16 at 21:27
|
show 8 more comments
$begingroup$
Hi, did you post your answer to the wrong page?
$endgroup$
– piojo
Aug 16 at 16:56
$begingroup$
@pojo: Perhaps I should have made clearer that the purpose of the answer is to identify a situation where using properties rather than fields is bad, and identify how one can achieve the performance and semantic advantages of fields, while still encapsulating access.
$endgroup$
– supercat
Aug 16 at 17:42
$begingroup$
@piojo: Does my edit make things clearer?
$endgroup$
– supercat
Aug 16 at 17:55
$begingroup$
"will need to read all 26 fields of list[0] even though it will ignore all but two of them." what? Are you sure? Have you checked the MSIL? C# nearly always passes class types by reference.
$endgroup$
– pjc50
Aug 16 at 20:23
$begingroup$
@pjc50: Reading a property yields a result by value. If both the indexed getter forlist
and the property getter forab
are both in-lined, it might be possible for a JITter to recognize that only membersa
andb
are needed, but I'm unaware of any JITter version actually doing such things.
$endgroup$
– supercat
Aug 16 at 21:27
$begingroup$
Hi, did you post your answer to the wrong page?
$endgroup$
– piojo
Aug 16 at 16:56
$begingroup$
Hi, did you post your answer to the wrong page?
$endgroup$
– piojo
Aug 16 at 16:56
$begingroup$
@pojo: Perhaps I should have made clearer that the purpose of the answer is to identify a situation where using properties rather than fields is bad, and identify how one can achieve the performance and semantic advantages of fields, while still encapsulating access.
$endgroup$
– supercat
Aug 16 at 17:42
$begingroup$
@pojo: Perhaps I should have made clearer that the purpose of the answer is to identify a situation where using properties rather than fields is bad, and identify how one can achieve the performance and semantic advantages of fields, while still encapsulating access.
$endgroup$
– supercat
Aug 16 at 17:42
$begingroup$
@piojo: Does my edit make things clearer?
$endgroup$
– supercat
Aug 16 at 17:55
$begingroup$
@piojo: Does my edit make things clearer?
$endgroup$
– supercat
Aug 16 at 17:55
$begingroup$
"will need to read all 26 fields of list[0] even though it will ignore all but two of them." what? Are you sure? Have you checked the MSIL? C# nearly always passes class types by reference.
$endgroup$
– pjc50
Aug 16 at 20:23
$begingroup$
"will need to read all 26 fields of list[0] even though it will ignore all but two of them." what? Are you sure? Have you checked the MSIL? C# nearly always passes class types by reference.
$endgroup$
– pjc50
Aug 16 at 20:23
$begingroup$
@pjc50: Reading a property yields a result by value. If both the indexed getter for
list
and the property getter for ab
are both in-lined, it might be possible for a JITter to recognize that only members a
and b
are needed, but I'm unaware of any JITter version actually doing such things.$endgroup$
– supercat
Aug 16 at 21:27
$begingroup$
@pjc50: Reading a property yields a result by value. If both the indexed getter for
list
and the property getter for ab
are both in-lined, it might be possible for a JITter to recognize that only members a
and b
are needed, but I'm unaware of any JITter version actually doing such things.$endgroup$
– supercat
Aug 16 at 21:27
|
show 8 more comments
Thanks for contributing an answer to Game Development Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgamedev.stackexchange.com%2fquestions%2f174659%2fis-the-microsoft-recommendation-to-use-c-properties-applicable-to-game-developm%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
34
$begingroup$
Always verify with a profiler before believing something is "slow". I was told something was "slow" and the profiler told me it had to execute 500,000,000 times to lose a half second. As it would never execute more than a few hundred times in a frame, I decided it was irrelevant.
$endgroup$
– Almo
Aug 15 at 13:46
5
$begingroup$
I've found that a little bit of abstraction here and there helps to apply low-level optimizations more widely. For instance, I've seen numerous plain C projects using various kinds of of linked-lists, which are dreadfully slow compared to contiguous arrays (e.g. the backing for
ArrayList
). This is because C has no generics, and these C programmers likely found it easier to repeatedly re-implement linked-lists than to do the same forArrayLists
's resizing algorithm. If you come up with a good low-level optimization, encapsulate it!$endgroup$
– hegel5000
Aug 15 at 17:46
3
$begingroup$
@Almo Do you apply that same logic to operations that occur in 10,000 different places? Because that is class member access. Logically you should be multiplying the performance cost by 10K before deciding that class of optimization doesn't matter. And 0.5 ms is a better rule of thumb for when the performance of your game will be ruined, not half a second. Your point still stands, though I don't think the right action is as clear as you make it out to be.
$endgroup$
– piojo
Aug 16 at 3:08
5
$begingroup$
You have 2 horses. Race them.
$endgroup$
– Mast
Aug 16 at 11:48
$begingroup$
@piojo I do not. Some thought must always go into these things. In my case, it was for loops in UI code. One UI instance, few loops, few iterations. For the record, I upvoted your comment. :)
$endgroup$
– Almo
Aug 16 at 16:14