27 comments

[ 2.4 ms ] story [ 58.6 ms ] thread
Being able to disable blocking gen 2 GCs for a period of time will be really useful for games and multimedia applications. You can disable the blocking GC during your update/render logic, then turn it back on while your main thread is blocked on vertical sync!

Being able to do this kind of scheduling aware GC would be a big boon for browser environments too. I've been pushing browser developers to do this and hopefully having working examples of it in other environments will help motivate them - see https://bugzilla.mozilla.org/show_bug.cgi?id=730113 for one example of how this might be done.

That is not a very good idea, a gc could easily take more time than your vsync, even if you didn't leak anything. It's smarter to profile your game and make sure it doesn't leak any memory, and perhaps use this feature to disable the GC altogether until play is interrupted.
How exactly do you propose 'not leaking memory' in runtime environments where everything creates garbage? In .NET you at least have structs, but other environments (like JS as I gave as an example) make it impossible or near-impossible to be garbage-free. Controlling the timing of your GCs is a win there, even if a long GC can make you miss a frame.

Half a GC happening during vsync instead of none of it is still a win because the hitch will be smaller.

Wether the language has structs or not has nothing to do with leaking garbage. I think it's even possible to not leak memory in js, though I haven't tried that.

It is absolutely not true that everything in .net creates garbage. If you leak memory in your render/update loops then that's a problem. You prevent it by never calling new and never using syntax that implicitly allocates (like foreach).

Anyways, the half GCs still happen even if you enable the no gc mode. Going for the small hitch instead of for no hitch at all seems to be setting the bar too low for me. (no matter how small the hitch, if it consistently happens players will notice it and your game experience will be seriously degraded)

edit: just checked out your profile, you obviously know more of what creates garbage in js than I do, so I'll believe you if you say everything creates garbage :)

You may end up writing C...
If you regard watching your memory allocations as a C thing, then perhaps. When you build real time video games this is just how it goes, whatever language you work in. You need to make sure everything is allocated _before_ you enter the game loop, wether it's C or C#.

Even when you feel bothering with those details is like programming C, you still have classes, namespaces, a sane compiling and linking system and a terrific standard library. Which in my opinion makes it infinitely more comfortable than coding in C.

Note that the usually the OOP system heavily promotes short-lived memory allocations and the standard library is build around it.
Foreach in C# doesn't always create garbage, FYI. Enumerators can be structs - List<T>'s is, for example.

It's certainly possible to write an application that doesn't structurally create garbage, but doing so isn't a universal win. Garbage-free coding patterns are more verbose, harder to get right, and often slower than relying on the GC.

The reason a small hitch is better than no hitch is that if your game is running faster than your target framerate, hitches can be small enough to actually hide between frames - and control over when the GC occurs can allow you to reliably hide your GCs there.

Structs can implement IEnumerator<T> as you mentioned, but they need to be boxed before any interface methods they implement can be called.

So, foreach in C# does always create at least a tiny bit of garbage -- but in the case above it's likely to be reclaimed very quickly.

Normally value types do need to be boxed before calling interface methods, but C#'s `foreach` statement is special in that the collection expression just needs to conform to the "collection pattern" rather than implement a particular interface (i.e. IEnumerable).

An expression conforms to the collection pattern if it has a public `GetEnumerator` method that returns a type that has a public method of type `MoveNext -> bool` and a public method of type `Current -> Type_Of_The_Element`.

In other words, `foreach` uses structural typing rather than nominal typing.

Incidentally, value types need only generate garbage in a `foreach` statement if they create a disposable `Enumerator`.

Interesting -- I'd read about this once before but forgotten all about it. Good catch!
SustainedLowLatency is a killer for many types of scenarios. One is when you create many objects that you don't intent to GC throughout the life of the app, dictionaries for example.

Memory is cheap, being able to use it to increase performance of a managed app makes me really excited with how c# can be used in apps typically written in C++

> "The new background server GC in the .NET Framework 4.5 offloads much of the GC work associated with a full blocking collection to dedicated background GC threads that can run concurrently with user code, resulting in much shorter (less noticeable) pauses. One customer reported a 70% decrease in GC pause times. "

Concurrent garbage collection. Not that impressive in 2012. Java has had concurrent GC for at least a decade:

JDK 1.2.2 Java had a switch for that in the late 90's already: -Xconcgc Use concurrent garbage collector (1.2.2_07+)

JDK 1.4.2 http://java.sun.com/docs/hotspot/gc1.4.2/#4.3.%20When%20to%2...

also: http://research.sun.com/techrep/2000/abstract-88.html

The world has moved on:

http://www.oracle.com/technetwork/java/javase/tech/g1-intro-...

http://researcher.watson.ibm.com/researcher/view_project_sub...

Many other languages still don't have it, as I understand it implementing a concurrent garbage collector is always impressive, whether you did it 20 years ago or now.

I think this is indicative of their priorities. Java has had to fight the general opinion that it is a slow platform, so they built the best garbage collecting vm you could imagine. .Net has had to fight the opinion that it is just Java but on windows, so they built a multiple language oriented vm that enables language features so varied that even the standard java-like language C# rivals ruby and python in expression.

> built a multiple language oriented vm that enables language features so varied that even the standard java-like language C# rivals ruby and python in expression

Since the JVM happily runs Ruby, Groovy, Clojure, Python, Scala the point it moot. Aside from that C# does not rival Ruby in expressiveness.

The point is not moot that .Net was designed to support multiple languages, regardless of wether multiple languages run on the JVM.

The JVM was designed to support only one language, Java, it is generic enough to run any language, but not efficiently or easily per se. The bytecode language is not standardized, and there is no standard assembler language for it. New features to the JVM are only added when they are required for Java.

In contrast the instruction language and bytecode of .net are standardized and it has a standard assembler language, with an actual assembler and disassembler. Design of the CLR is actually driven by multiple languages like F# and the Iron projects.

I'll bet you that the creators of JRuby and Clojure would love to have the features the CLR offers.

I say it does rival ruby, you say it doesn't, good discussion.

The point my original post makes is that .NET having concurrent GC is not exactly groundbreaking. This doesn't have anything to do with the so-called expressiveness of C# relative to Ruby.

>The bytecode language is not standardized, and there is no standard assembler language for it

There is a formal spec here: http://docs.oracle.com/javase/specs/jvms/se7/jvms7.pdf

> New features to the JVM are only added when they are required for Java.

This is another false assumption: http://blog.headius.com/2008/09/first-taste-of-invokedynamic...

>I say it does rival [the expressiveness of] ruby, you say it doesn't, good discussion.

Not really, is more like a generally accepted fact. e.g. Ruby typically uses 2-3x less code than C# to do the same thing: http://shootout.alioth.debian.org/u64q/benchmark.php?test=al...

> There is a formal spec

Not really the same thing as an ECMA standard http://www.ecma-international.org/publications/standards/Ecm...

> Ruby typically uses 2-3x less code than C#

Perhaps you wanted to use a different link? This one says that it is ~10 times slower?

Everyone knows that ruby is ~10 times slower than anything else the question is how the expressiveness compares.

Of course the amount is code is going to be greater because you are more explicit about types. I program in ruby for a living and do some C# as a hobby so I know the differences..

> Perhaps you wanted to use a different link? This one says that it [ruby] is ~10 times slower [than C#]?

The link is correct. See the "code" section where Ruby has 2-3x less code. I won't disagree about Ruby being much slower than C# and Java. Ruby slow[er]ness has to do with it being dynamically typed, which also makes it expressive. If you are after something which is more expressive than C# and faster than C# see Scala on the JVM: http://shootout.alioth.debian.org/u64q/benchmark.php?test=al...

You do realize that .NET has had concurrent garbage collection for a decade? It was workstation-only until recently (now?).

But background GC is different than concurrent GC (in the .NET world) in that background GC can collect ephemeral generations in the middle of a gen 2 background collection (this was a restriction of concurrent GC in the past). Background GC is in the current version of .NET, but it sounds like they've extended background GC to the server now.

While there are some great JVM GCs, I wouldn't walk away with the impression that the .NET folks are behind by any means.

(comment deleted)