I keep seeing examples online, where there is a property of an element within a method that is copied to a local variable before use. For example, something like this (from Microsoft's StackPanel source code):
UIElementCollection children = arrangeElement.InternalChildren;
...
for (int i = 0, count = children.Count; i < count; ++i)
{
UIElement child = (UIElement)children[i];
if (child == null) { continue; }
...
}
Can anyone explain to me what the benefit of doing that is (if there is one), rather than accessing the property directly each time, like this?:
for (int i = 0, count = arrangeElement.InternalChildren.Count; i < count; ++i)
{
UIElement child = (UIElement)arrangeElement.InternalChildren[i];
if (child == null) { continue; }
...
}
Clearly, it saves a few characters on the screen, but that's not much of a reason to do this. Also, I understand why we might want to do this with a long running method, as a form of caching:
double value = GetValueFromLongRunningMethod();
...
for (int i = 0; i < someCollection.Count; i++) DoSomethingWith(value);
But I see this done with properties a lot and wonder why. Here's another commonly found example from the internet to do with virtualization:
IItemContainerGenerator generator = this.ItemContainerGenerator;
GeneratorPosition position = generator.GeneratorPositionFromIndex(firstVisibleItemIndex);
Why do that instead of this?:
GeneratorPosition position =
this.ItemContainerGenerator.GeneratorPositionFromIndex(firstVisibleItemIndex);
Finally, if this is done for the same reason that we might cache the result of a long running method, then how are we supposed to know which properties need to be accessed in this way?
Firstly, it avoids calling .InternalChildren lots of times. This could be a small but noticeable reduction of virtual calls (since it is used in a loop), but in some cases it might be much more significant. In some cases, a property that returns a collection or array might allocate every time it is called; DataRow.ItemArray is a classic example of this - so it is actively harmful to call it each time. An additional consideration is that even if it returns the same array each time it is called, there is JIT magic that happens to elide bounds checking, but it'll only work if the JIT can see that you are iterating a single array for the entire duration. If you stick a property accessor in the middle: this won't be obvious and the bounds check removal won't happen. It also might not happen if you've manually hoisted the upper bound!
Side note: if it isn't an array, then foreach would probably usually be preferable, and there would not be any advantage to introducing a local, due to how foreach works internally.
Note: since you're using .Count vs .Length, this definitely isn't an array, and you should probably simplify to:
foreach(UIElement child = in arrangeElement.InternalChildren) {...}
or
foreach(var child = in arrangeElement.InternalChildren) {...}
Not only does this remove this question completely, but it means that the type's own iterator (which might be an optimized struct iterator, or might be a simple IEnumerable<T> class, such as a compiler-generated iterator block) can be used. This usually has more direct access to the internals, and thus bypasses a few indirections and API checks that indexers require.
It might be fruitful in some cases like when you have to
debug some piece of code and you need to instantly see the value of variable
do a few operations at a time with an object, which requires casting - as result you cast it once
and sometimes, when you use value type objects this kind of making a local copy gives you an opportunity to not change the value of class' property
Why do that instead of this?:
GeneratorPosition position =
this.ItemContainerGenerator.GeneratorPositionFromIndex(firstVisibleItemIndex);
Let's get very abstract about this:
We get a generator. That apparently is this.ItemContainerGenerator for now, but that could change.
We use it. Only once here, but usually in multiple statements.
When we later decide to get that generator elsewhere, the usage should stay the same.
The example is too small to make this convincing, but there is some kind of logic to be discerned here.
Related
I have a code using third-party-tool iterating over a collection of points.
for (int i = 0; i < pcoll.PointCount; i++) { /* ... */ }
When doing profiling via dotTrace I noticed that the PointCount-proerty is accessed every iteration (see picture above)
.
I expected that the value for this property is optimized away by the compiler but obviously that doesn't happen. Maybe this is actually a problem within the COM-based 3rd-party lib or also within dotTrace self when collecting the information.
I'm not sure if this topic wouldn't fit better to Gis.StackExchange. However maybe someone has any idea under which circumstances optimzation won't take place or how it might happen.
Simply put, how is the compiler to know whether pcoll.PointCount will change between invocations? It can't safely make the assumption that the value will remain unchanged, so it can't optimise this code by caching the value of the first call to pcoll.PointCount.
It may have changed in the meantime.
Indeed, one of the reasons to test i < pcoll.PointCount every iteration rather than just using foreach(var point in pcoll) is precisely because you think the collection might change in the meantime, and enumerators don't guarantee to cope with changes to the collection they enumerate.
This differs from, for example, an array accessed through a local variable, because the only way the Length of an array accessed through a local variable can change, is if the change is made locally.
Even there though, it's worth remembering that the compiler often skips some obvious optimisations because it's known that the jitter makes the same optimisation too.
The expected optimization is true for fields. But property has setter/getter (accessing property is in fact calling them as methods), so compiler will have hard time to try to optimize it.
To fix, make it a field or read it once
var max = pcoll.PointCount;
for (int i = 0; i < max; i++) { /* ... */ }
Wonder if anyone could explain what is going on with this weird little optimisation in our draw code. We replaced the first little bit of code with the second and got a huge speed increase (4400 tick -> 15 ticks using stopwatch class)
// Add all the visible sprites to the list
m_renderOrder.Clear();
foreach (CSpriteInternalData sprite in m_InternalData)
{
if (!sprite.m_bRender) continue;
m_renderOrder.Add(sprite);
}
Replaced with...
// Add all the visible sprites to the list
m_renderOrder.Clear();
renderOrderCount = 0;
for (int i = 0; i < m_numSprites; i++ )
{
if (m_InternalData[i].m_bRender)
m_renderOrder[renderOrderCount++] = m_InternalData[i];
}
I looks to be the simplest little change, for such a huge increase in speed. Can anyone help?
If CSpriteInternalData is a struct, i.e. a value type, each time when you assign a value of that type to a variable, a copy is done.
MyStruct a = new MyStruct(50);
MyStruct b = a; //a is copied to b;
a.Value = 10;
Console.WriteLine(b.Value); //still 10, has a separate copy of value
If structs are small and portable, that is not much of a problem, but if the structs are large, they can get slow. Foreach creates a variable that is repeatedly assigned a value from the collection, so if CSpriteInternalData is a struct, each one is in turn copied to the sprite variable, and that could take time.
Also, the line when you Add the item to the m_renderOrder collection, invokes another copy of the structure, but I guess only a few of them have the m_bRender flag set, so that one does not take too much time.
If that is the cause of the slowdown / speedup I would wholeheartedly recommend that you change CSpriteInternalData to a class, that would use reference behavior, and just copy references around, instead of whole copies.
foreach always creates an instance of an enumerator that is returned by GetEnumerator method and that enumerator also keeps state throughout the life cycle of the foreach loop.
It then repeatedly calls for the Next() object on the enumerator and runs your code for each object it returns.
You can create you own emulator in case. But better to user for loop instead when execution time matters.
The foreach loop has a slightly different purpose. It is meant for itterating through some collection that implements IEnumerable. It's performance is much slower.
for the reference you can see
http://www.codeproject.com/Articles/6759/FOREACH-Vs-FOR-C
I am making a XNA game and I am calling following code 2 to 20 times per update. I tried googling and it seems like this is semi-slow, so I just thought I'd ask if there is any faster way to compare types?
Code:
public Modifier this[Type type]
{
get
{
for (int i = 0; i < this.Count; i++)
{
if (this[i].GetType() == type)
{
return this[i];
}
}
throw new NotImplementedException("Fix this");
}
set
{
for (int i = 0; i < this.Count; i++)
{
if (this[i].GetType() == type)
{
this[i] = value;
}
}
if(System.Diagnostics.Debugger.IsAttached)
System.Diagnostics.Debugger.Break();
}
}
This code is in ModifierCollection class which inherits from a List. Modifier is a part of particle engine. Also, my game isnt in condition where I can actually test this yet so I cant test this, but this should work right?
I read something about RunTimeTypeHandles which should be faster, should I use it?
EDIT: What I am aiming to do with this is that I can do the following:
(particleEffect["NameOfEmitter"].Modifiers[typeof(SomeCoolModifier)] as SomeCoolModifier).Variable = Value;
Basically I just want to change the value of some Modifiers in runtime.
EDIT 2: I just realized that I can just save the reference of Modifier to the class where I am at the moment calling this :P Maybe not as clean code if I have 5-10 modifiers but should remove this problem.
If you don't need any of the extra functionality exposed by Type, and you're only concerned with absolute equality between types--i.e., you don't need to support inheritance--RuntimeTypeHandle is the fastest way to do this comparison.
Really, though, I would question whether this isn't a weakness of your class design. Unless you have a compelling reason to check the type directly, it's probably better to expose some sort of value (probably an enum) on your objects that represents what they are, and do your comparisons against that.
If you want to be really fast and can trust the code that is calling you, change the indexer to just take an int. Then in whatever method (which you didn't show) that callers use to add Types to the list, return back to them the corresponding int. It's a worse API but it means you don't have to do any loops or lookups.
You could store the values in a dictionary indexed by type rather than a list so you wouldn't have to do an O(n) iteration over the list each time.
As noted in the comments, this does depend on the size of n and may be a micro-optimization. I'd recommend profiling your application.
List<int> list = ...
for(int i = 0; i < list.Count; ++i)
{
...
}
So does the compiler know the list.Count does not have to be called each iteration?
Are you sure about that?
List<int> list = new List<int> { 0 };
for (int i = 0; i < list.Count; ++i)
{
if (i < 100)
{
list.Add(i + 1);
}
}
If the compiler cached the Count property above, the contents of list would be 0 and 1. If it did not, the contents would be the integers from 0 to 100.
Now, that might seem like a contrived example to you; but what about this one?
List<int> list = new List<int>();
int i = 0;
while (list.Count <= 100)
{
list.Add(i++);
}
It may seem as if these two code snippets are completely different, but that's only because of the way we tend to think about for loops versus while loops. In either case, the value of a variable is checked on every iteration. And in either case, that value very well could change.
Typically it's not safe to assume the compiler optimizes something when the behavior between "optimized" and "non-optimized" versions of the same code is actually different.
The C# compiler does not do any optimizations like this. The JIT compiler, however, optimizes this for arrays, I believe (which are not resizable), but not for lists.
A List's count property can change within the loop structure, so it would be an incorrect optimization.
It's worth noting, as nobody else has mentioned it, that there is no knowing from looking at a loop like this what the "Count" property will actually do, or what side effects it may have.
Consider the following cases:
A third party implementation of a property called "Count" could execute any code it wished to. e.g. return a Random number for all we know. With List we can be a bit more confident about how it will operate, but how is the JIT to tell these implementations apart?
Any method call within the loop could potentially alter the return value of Count (not just a straight "Add" directly on the collection, but a user method that is called in the loop might also party on the collection)
Any other thread that happens to be executing concurrently could also change the Count value.
The JIT just can't "know" that Count is constant.
However, the JIT compiler can make the code run much more efficiently by inlining the implementation of the Count property (as long as it is a trivial implementation). In your example it may well be inlined down to a simple test of a variable value, avoiding the overhead of a function call on each iteration, and thus making the final code nice and fast. (Note: I don't know if the JIT will do this, just that it could. I don't really care - see the last sentence of my answer to find out why)
But even with inlining, the value may still be changed between iterations of the loop, so it would still need to be read from RAM for each comparison. If you were to copy Count into a local variable and the JIT could determine by looking at the code in the loop that the local variable will remain constant for the loop's lifetime, then it may be able to further optimise it (e.g. by holding the constant value in a register rather than having to read it from RAM on each iteration). So if you (as a programmer) know that Count will be constant for the lifetime of the loop, you may be able to help the JIT by caching Count in a local variable. This gives the JIT the best chance of optimising the loop. (But there are no guarantees that the JIT will actually apply this optimisation, so it may make no difference to the execution times to manually "optimise" this way. You also risk things going wrong if your assumption (that Count is constant) is incorrect. Or your code may break if another programmer edits the contents of the loop so that Count is no longer constant, and he doesn't spot your cleverness)
So the moral of the story is: The JIT can make a pretty good stab at optimising this case by inlining. Even if it doesn't do this now, it may do it with the next C# version. You might not gain any advantage by manually "optmising" the code, and you risk changing its behaviour and thus breaking it, or at least making future maintenance of your code more risky, or possibly losing out on future JIT enhancements. So the best approach is to just write it the way you have, and optimise it when your profiler tells you that the loop is your performance bottleneck.
Hence, IMHO it's interesting to consider/understand cases like this, but ultimately you don't actually need to know. A little bit of knowledge can be a dangerous thing. Just let the JIT do its thing, and then profile the result to see if it needs improving.
If you take a look at the IL generated for Dan Tao's example you'll see a line like this at the condition of the loop:
callvirt instance int32 [mscorlib]System.Collections.Generic.List`1<int32>::get_Count()
This is undeniable proof that Count (i.e. get_Count()) is called for every iteration of the loop.
For all the other commenters who say that the 'Count' property could change in a loop body: JIT optimizations let you take advantage of the actual code that's running, not the worst-case of what might happen. In general, the Count could change. But it doesn't in all code.
So in the poster's example (which might not have any Count-changing), is it unreasonable for the JIT to detect that the code in the loop doesn't change whatever internal variable List uses to hold its length? If it detects that list.Count is constant, wouldn't it lift that variable access out of the loop body?
I don't know if the JIT does this or not. But I am not so quick to brush this problem off as trivially "never."
No, it doesn't. Because condition is calculated on each step. It can be more complex than just comparsion with count, and any boolean expression is allowed:
for(int i = 0; new Random().NextDouble() < .5d; i++)
Console.WriteLine(i);
http://msdn.microsoft.com/en-us/library/aa664753(VS.71).aspx
It depends on the particular implementation of Count; I've never noticed any performance issues with using the Count property on a List so I assume it's ok.
In this case you can save yourself some typing with a foreach.
List<int> list = new List<int>(){0};
foreach (int item in list)
{
// ...
}
According to [MSDN: Array usage guidelines](http://msdn.microsoft.com/en-us/library/k2604h5s(VS.71).aspx):
Array Valued Properties
You should use collections to avoid code inefficiencies. In the following code example, each call to the myObj property creates a copy of the array. As a result, 2n+1 copies of the array will be created in the following loop.
[Visual Basic]
Dim i As Integer
For i = 0 To obj.myObj.Count - 1
DoSomething(obj.myObj(i))
Next i
[C#]
for (int i = 0; i < obj.myObj.Count; i++)
DoSomething(obj.myObj[i]);
Other than the change from myObj[] to ICollection myObj, what else would you recommend? Just realized that my current app is leaking memory :(
Thanks;
EDIT: Would forcing C# to pass references w/ ref (safety aside) improve performance and/or memory usage?
No, it isn't leaking memory - it is just making the garbage collector work harder than it might. Actually, the MSDN article is slightly misleading: if the property created a new collection every time it was called, it would be just as bad (memory wise) as with an array. Perhaps worse, due to the usual over-sizing of most collection implementations.
If you know a method/property does work, you can always minimise the number of calls:
var arr = obj.myObj; // var since I don't know the type!
for (int i = 0; i < arr.Length; i++) {
DoSomething(arr[i]);
}
or even easier, use foreach:
foreach(var value in obj.myObj) {
DoSomething(value);
}
Both approaches only call the property once. The second is clearer IMO.
Other thoughts; name it a method! i.e. obj.SomeMethod() - this sets expectation that it does work, and avoids the undesirable obj.Foo != obj.Foo (which would be the case for arrays).
Finally, Eric Lippert has a good article on this subject.
Just as a hint for those who haven't use the ReadOnlyCollection mentioned in some of the answers:
[C#]
class XY
{
private X[] array;
public ReadOnlyCollection<X> myObj
{
get
{
return Array.AsReadOnly(array);
}
}
}
Hope this might help.
Whenever I have properties that are costly (like recreating a collection on call) I either document the property, stating that each call incurs a cost, or I cache the value as a private field. Property getters that are costly, should be written as methods.
Generally, I try to expose collections as IEnumerable rather than arrays, forcing the consumer to use foreach (or an enumerator).
It will not make copies of the array unless you make it do so. However, simply passing the reference to an array privately owned by an object has some nasty side-effects. Whoever receives the reference is basically free to do whatever he likes with the array, including altering the contents in ways that cannot be controlled by its owner.
One way of preventing unauthorized meddling with the array is to return a copy of the contents. Another (slightly better) is to return a read-only collection.
Still, before doing any of these things you should ask yourself if you are about to give away too much information. In some cases (actually, quite often) it is even better to keep the array private and instead let provide methods that operate on the object owning it.
myobj will not create new item unless you explicitly create one. so to make better memory usage I recommend to use private collection (List or any) and expose indexer which will return the specified value from the private collection