Performance cost of 'new' in C#?
Asked Answered
S

10

43

In C# what is the performance cost of using the new keyword? I ask specifically in relation to games development, I know in C++ it is a definite no-no to be newing things every update cycle. Does the same apply to C#? I'm using XNA and developing for mobile. Just asking as an optimization question really.

Species answered 23/11, 2010 at 7:33 Comment(3)
Do you think your question really warrants the C++ tag? Your question has nothing to do with C++, and could be asked without the sentence that mentions it. (In other words, someone with no experience in C++ could answer this question.)Herald
I would rather someone with C++ experience answers this question because I have a background as a C++ programmer and want to know about the nuanced differences it has with C#.Species
You should probably read this blog post: blogs.msdn.com/b/shawnhar/archive/2007/07/02/… the problem isn't so much new as it the possibility of it triggering a garbage collection. (new itself is crazy-fast.)Meiny
I
42

There are three parts to the cost of new:

  • Allocating the memory (may not be required if it's a value type)
  • Running the constructor (depending on what you're doing)
  • Garbage collection cost (again, this may not apply if it's a value type, depending on context)

It's hard to use C# idiomatically without ever creating any new objects in your main code... although I dare say it's feasible by reusing objects as heavily as possible. Try to get hold of some real devices, and see how your game performs.

I'd certainly agree that micro-optimization like this is usually to be avoided in programming, but it's more likely to be appropriate for game loops than elsewhere - as obviously games are very sensitive to even small pauses. It can be quite hard to judge the cost of using more objects though, as it's spread out over time due to GC costs.

The allocator and garbage collector is pretty good in .NET, although it's likely to be simpler on a device (Windows Phone 7, I assume)? In particular, I'm not sure whether the Compact Framework CLR (which is the one WP7 uses) has a generational GC.

Interplead answered 23/11, 2010 at 7:36 Comment(5)
Compact Framework doesn't has generational GC -- at least, last time I checked. But that was back in the PocketPC 2003 days, when most devices had only 32MB of ram...Idola
@Rei: Yes, older versions definitely didn't. Not sure about 3.7, which is what's in WP7.Interplead
Hmm, it'd be cool to devise an experiment to find out. Would be a challenge though.Idola
@JonSkeet: can the usage of Singleton help to avoid creating too many objects?Ardine
@MagB: Yes, but the inflexibility of it still makes it worth avoiding in most cases, IMO.Interplead
I
27

Allocation in C# is actually faster than in C++. It just involves increasing the heap pointer and returning that pointer. Generally, objects get newed up more often in C# than in C++, as there is a bit more immutability involved in things like strings.

As others have pointed out, the real beast is the garbage collector, which is a bit tricky to profile. Nonetheless, even GCing is in most cases just as fast if not faster than delete in C++ -- just that you can't predict when it'll happen.

Some hints by Rico Mariani, the perf guy on the .NET team: http://msdn.microsoft.com/en-us/library/ms973837.aspx

It's a bit old and there have been a few improvements on the GC, but most of the information is still relevant.

I should add though that the XNA/Compact Framework Garbage Collector is somewhat slower than in the x86 version to trade off CPU for memory performance, so you should beware of that.

EDIT

I forgot to mention, and this is important: value types, including structs, use the new syntax too, but they're created on the stack rather than on the heap, so there's no GC cost for those unless you box them.

Idola answered 23/11, 2010 at 7:52 Comment(4)
+1 for good discussion about GC, and being correct. The biggest problem with memory allocation in games is that the garbage collector will stop all your threads to do a collection. This can very easily cause a frame-rate hiccup.Meiny
Yeah, there are multiple available GC implementations to account for that. On Windows, there's the server GC which IIS uses and the application GC which .exes use by default. The server one is more thorough and less frequent but locks all the threads for a longer period of time. If we're lucky, they'll have adjusted the CF/XNA one to be more frequent and with shorter locks.Idola
Not sure about the phone. But the Xbox 360 one runs every 1MB of allocation and is non-generational. It's slow enough that you need to care about it. The Windows one, on the other hand, is ok for game development in most circumstances.Meiny
Of course a value type on the stack which contains a reference needs to be collected; not because it might be dead but because the reference it contains might be alive. Stack-allocated value types that contain reference types still contribute cost to the GC.Nakesha
E
7

The cost of the new operator itself is negligible. What might cost is the processing that happens in a custom constructor. So if you have lots of things going on in this constructor it could be a problem.

Etam answered 23/11, 2010 at 7:34 Comment(0)
G
5

You should always code the "easiest" way then measure bottlenecks, if they are present.

Anyway, I'd never code games in C# .

EDIT

Since it caused resentment, I mean that I'd never code in C# if C++ was an option available. This is what I thought since the OP also tagged C++.

Gudrun answered 23/11, 2010 at 7:36 Comment(4)
Afaik Caesar IV is written in C#, at least partly - just horrible, it's as if you can tell when the GC is running :)Mosby
If the OP is developing for WP7, then the only other option is VB. IS THIS WHAT YOU WANT?!?Vortex
You're not only worried about bottlenecks on mobile apps, you're also worried about battery consumption.Idola
@Armen - Quick Googling learns me that it uses C# for game logic, which, if properly applied (jitted) will give a performance boost over using scripting languages such as Lua or UnrealScript.Rugg
C
4

The cost of new itself is most likely not significant, but as allocating new objects on the heap (when creating instances of reference types) may trigger a garbage collection, the side effect may be significant in a game. If you're worried about GC you can either use value types or reuse objects.

Also, as Darin correctly points out, the constructor may do a lot of work.

Cluck answered 23/11, 2010 at 7:36 Comment(0)
R
2

There is almost no cost associated with new operator in c# but when you use new on reference type , a heap allocation will be there and this is maintained by GC. If the memory is contineous than allocating memory is just a pointer movement but if the GAP between two allocations are found than GC will consult a free list of avaliable memory (a link list) to find the required object this will some time requiries o(n) travelsal time.

See Post By Eric Lippert

Reconnoiter answered 23/11, 2010 at 7:46 Comment(0)
M
1

In C# the memory is kept defragmented by the Garbage Collector, so finding and allocating memory is a very fast operations. However the occasional defragmentation performed by GC can slow down considerably

Mosby answered 23/11, 2010 at 7:35 Comment(0)
D
1

When you write new in c# the CLR allocates memory to the object on managed heap.

Please look at the below link for more on this :

http://msdn.microsoft.com/en-us/library/ee787088(v=vs.100).aspx

Since the garbage collection is automatic in C# (only case when during testing people use GC.Collect to manually trigger it) , game design on c# is a bad idea.

You should look for C++ for the purpose as there you have destructors.

~ClassName()
{
//kill my object and reclaim memory.
}
Daryldaryle answered 4/9, 2013 at 5:34 Comment(0)
H
1

Normally, it's a performance black hole for c# to miss the stack allocation for micro structure like Rect, Point and all others. Space allocation on the stack is just bp:sp = bp:sp + size for the cpu, while heap allocation with New require many algorithm, gc control, large memory page size, eventualy on disk, relocation, etc

Hennie answered 7/4, 2020 at 6:42 Comment(0)
C
0

My measurement shows, a "new" to reference type can sometimes take as long as 2.2 seconds and can sometimes be as fast as a few ticks. Bottom line is that there is no real-time guarantee in .net GC and performance can vary significantly in random manner. So I'd suggest for real-time designs, e.g. gaming, don't call "new" to reference types in the real-time part of your code (e.g. update loops), for there is no real-time guarantee.

Of course, many people will argue that how often a "new" would take 2.2 seconds and does it matter if happens only once of several hours. Well this has to be the judgement of the designer. But for the sake of academic arguments, GC is not real-time, hence don't call "new" in real-time codes.

Cannonade answered 13/10, 2015 at 3:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.