问题
What is the performance of testing whether a reference-type variable in C# is a null-pointer (like if (x == null)
...) compared to testing for an integer being smaller than zero or even a bool being false?
Are there other issues know regarding such null-pointer tests, e.g. is garbadge produced?
I do hundred of these tests for every frame of a game and I was wondering if these could cause problems or could be implemented more efficiently?
回答1:
Nullity tests are likely to be equivalent to simple "equal to 0" tests. They're very, very cheap - mere hundreds per frame should be completely insignificant unless you've got a frame rate in the millions :)
You should profile your app to find out where the time is actually being spent - it's a lot more productive than just guessing. Ideally, you should also try to write some benchmarks so that you can not only measure current performance, but also notice if it gets significantly worse due to any particular change.
回答2:
Testing a value for null is not a complicated operation that needs type checking or something like that, and there is no memory allocation involved.
Disassembling the statement if (x == null)
gives:
00000030 cmp qword ptr [rsp+20h],0
00000036 jne 000000000000004A
I.e. the test is implemented as a simple integer comparison of the pointer value.
回答3:
Doing intensive checks like you are may have some performance degradation, however, that can only be measureable by your own standards against your particular app.
Based on what the point of the test is, there is possibly other ways you could be smarter about what & when you check. However, without knowing more about your application it would be too difficult to try conjure up an answer to this.
回答4:
Probably subjective - but a null check is equivalent an equal-to-zero check, and just as quick. So I don't think you should be worrying about this.
Equally - unless you have performance problems why bother playing with it.
Also equally, if you do have performance problems, it's most likely that you'll be able to garner performance from complex branches of code rather than eliminating a few null checks.
That said, for conditional code, a potential performance improvement (however it would seriously need to be benchmarked) might be to use delegates for the different branches of logic that are set as the result of one or more conditions changes - but I'd be surprised if such a solution actually improves performance in the general case - especially for your 'is null' scenario. So, by that I mean something like this:
if([condition])
{
Foo();
}
else
{
Bar();
}
If, say, [condition]
involves a local variable _obj
(in your case _obj == null
) - you can replace with something like this (but be very very wary of threading issues):
private Action _logic;
private object _obj;
public Object Obj {
get { return Obj; }
set {
_obj=value;
if([condition])
_logic = () => Foo();
else
_logic = () => Bar();
}
}
And now in any code where you previously have checked [condition]
to do the branching you now simply do:
_logic();
This kind of thing gains most improvements when the [condition]
is complex and, crucially, has been proven to be taking up a lot of processor time through profiling. Using delegates will also carry a slight overhead over the conditional branching, but if that overhead is less then the execution of the [condition]
then it can make a difference, especially if those checks are being performed very frequently.
There are other variations of this too, most commonly function lookup tables derived from a value instead of choosing a branch of code based on an equality check (which is how large switch/case statements can be implemented - delegates added to a Dictionary
keyed by the enum/value being checked - which avoids multiple checks of the value).
Ultimately, though, without the due-diligence of profiling (before and after, of course), carrying out such optimisations is fundamentally pointless.
回答5:
No problems (performance or otherwise) with if (x == null)
.
回答6:
This should absolutely be no issue - all test you mention will usually take a single clock cycle. If there is a performance impact by conditional branches it is usually caused by unpredictable or at least hard to predict branching behaviour fouling the branch predictor and requiring abortion of the speculatively executed branch.
来源:https://stackoverflow.com/questions/14278595/null-pointer-test-performance