No, I am not kidding, after a week of optimizing I just reached almost 3 Mio FPS with our engine. I had to disable Clearing/Present and Input, but this is my log output (thanks to PerformanceCounters this is also pretty accurate): FPS: 2703785 With Input enabled I can easily go above 200000 FPS, most time of each frame is in whatever platform Input GetState method does: FPS: 202099 With Present (clear is not needed in my test as I draw a fullscreen quad) it goes down to ~13000 FPS, which is not shabby, but almost all time is lost in Present of XNA 4.0 CTP, which hasn't been optimized a lot yet by the XNA Team (the main module I use currently, but we support many different graphic frameworks as well, XNA is just the best for Windows IMO). Might sound crazy, but for performance checking I disable Present because then I immediately see whats slow in the render code. FPS: 12680 Other platforms are much worse, but it is always waiting for the graphic card or some external library, so I would say our engine is quite fast as of now. I obviously did not have much enabled in my test (just a test screen drawing a big quad, and Time, Input, Graphic, SceneManager, MaterialManager and Profiling modules enabled), but even doing more stuff does not hurt FPS wise. A more complex 2D screen could still achieve 10000 FPS. Next up is 3D optimization, which is much harder obviously (we are still not fast enough, especially on other platforms).
This is the last day of the MVP Summit. There will be one more post of tomorrows trip back to Germany, but it will probably be short. Today was not as interesting as the past few days because the Keynotes were pretty general. I wanted to see one of the side sessions, but it was exactly at lunch time when all XNA MVPs met up, which was way more important. Chuck Walbourn from the DirectX team (now called Windows Gaming Experience (WGX), which sounds strange IMO) did a great afternoon talk to any XNA/DirectX MVPs interested in DirectX11. This just made this day a great ending for the whole conference.

Since I was video chatting, blogging, emailing, etc. all morning I left the hotel a little later, the first keynote session was not so important for me. Later keynotes were not much better because I just don't like a presenter talking to serveral hundered guys and speaking slowly about some technology I probably don't have much impact on. I much rather watch those things online where I can skip over the boring parts :)

So instead I walked to the conference (which was at the Hyatt hotel again like in the first day) and took some pictures of Bellevue. As you can see not everything is Microsoft here, there are some other companies like Expedia located here.

But if you turn your head you can spot Microsoft pretty quickly again.

That big long building is the Westin hotel south of the Hyatt. From this angle looks very thin, but from the other side it is pretty large.

I like all these skyscrapers, maybe I should do a game with some buildings like these ^^

There is the Hyatt hotel where all the keynotes and side sessions are today. Pretty good weather today btw, I just had a T-Shirt and my new MVP jacket on.

These so called sky walkways are pretty useful because it takes forever until a light turns green here and you have to push a button at every single trafic light cross road section.

I just saw a little of the second keynote and then met some XNA MVPs, which were easy to spot because of our XNA MVP jackets we got from the XNA team. We then saw the last keynotes about clouds and hardware, software, etc. which was a bit better than the previous keynotes, but still very general (not a programmer session).

After that all the XNA MVPs met at the so called Farewell Lunch again. As usual lots of stories were traded and the food was very good.

After the lunch we took a few quick pictures of the group, which I can probably link up here later (I did not take a group foto except for this one because the other guys cameras are just much better at those things).

There was 45 minutes of free time between the lunch and the DirectX11 talk from Chuck, so I checked out the mall here.

As usual lots of schicki-micki shops here (thats what we say in Germany to way over the top fancy shops). Other than a Game Stop I could not found anything interesting here.

At the other side of the mall you could get back to the hotels via one of those sky walkways.

The directions were pretty confusing, but once I was on the right track I finally found the way back to the hotels for the last MVP session this year.

We had to wait a little because Chuck was hold up in traffic. I shot some extra pictures from the Cinema upstairs.

This are all the movies at this cinema, nothing to overly exciting I have not seen yet.

The last hardcore XNA/DirectX MVPs like Matt, Richard, Roy, Michael and a few others were listening to the DirectX11 presentations Chuck gave us quickly.

Chuck is talking fearlessly about all the cool new stuff and tricks in DirectX11. Most of those presentations and talks will be released publicly after the GDC in a few weeks, so stay tuned and check Chucks blog for that.

Time fly by and it is already late, time to head back and have a last look at Bellevue at night.

Pretty lights everywhere.

This little boy gives me the impression that he is trapped in there. But he is probably just pissing off his mom because in there it is much more amazing then out here.

Okay, thats it for today. I am really tired and will just watch some VODs this evening and read some websites. Tomorrow the long trip back to Germany will happen and I'm not sure that I will catch any sleep on the plane ..
The second deep session day was also very informative, but still very much top secret stuff. All this stuff will be announced on the GDC and MIX in a few weeks anyway, but I guess for a big company timing is everything for press releases.

It was very sunny today, I did not even take a jacket with me. The weather was still kinda cold, but since I will be indoor all day I do not really need a jacket.

While waiting for the bus a few other MVPs came along and asked me if I want to ride with them in their car to the summit. I said yes and we talked a bit about this summit and that it is way better this year that Microsoft actually tells us about new exciting stuff and not already publiced information as last year.

I arrived early and had some time to read emails and surf a little.

I also checked a few new websites and blogs other guys were talking about, like http://lostgarden.com/.

More XNA team members joined us today. These two are from education and website and product management.

In the lunch break we went to the company store. The Socksup guy also had to explain his nickname to everyone and it took longer the more drunk he was ^^

Shuttle cars and busses were taking MVPs back and forth from the hotels and Microsoft campus.

After walking around in circles for a while we finally got the the Company store, which was only a few hundered meters away from where we started ^^ Lots of products here, not much interesting stuff however.

There were a couple of older Xbox 360 games and I bought Ninja Gaiden for a few dollars, which is good as far as others told me. I also got some cheap t-shirts with some Windows logos on them.

The other guys also got some stuff and we quickly went back to our meeting room for more XNA talk.

In the meantime I was downloading StarCraft II beta (the beta started today finally), which took a long time. I could not do much else because the guest wifi was blocking all useful ports for VPN, VNC, IRC, etc. which was a little annoying because some programs I use depend on VPN working for example.

My netbook CPU should be way too slow for StarCraft II, but I installed it anyway. Still do not have a beta-key however, but I registered for the opt-in beta (which is probably bullshit anyway if millions of people trying to opt-in and they only give away a few more keys).

Okay, the long day is over (some of us were a little tired from too much partying yesterday) and we had some time to get back to the hotels, relax a little and then go to the big party this evening at the Garage in Seattle.

Nick (former MVP, now Microsoft employee) and some other XNA team guys are still talking to George Clingermann (XNA MVP).

On the bus ride back Dong-Hoon Kim (XNA MVP from Korea) and me took a few quick pictures from ourselfs. I learned some stuff about Korea and we talked about XNA and cultural differences quite a bit.

A little later we drove over to the Garage party location:

At the party, which was huge, you could play billard and

Bowling of course.

Lots of crazy drinks at the bar.

The XNA MVPs bunched up around Andy, who had lots of stories for us about his former Microsoft days and having meetings with Bill Gates in it and stuff like that.
A little while later you see some other MVPs talking and discussing stuff:

Other people also took quite a lot of pictures, which much better cameras however.

At 23:30 they tried get rid of us with telling us the last busses are leaving now.

The busses back to the hotel.

And finally reaching the hotel at 00:00, time to go to bed early today (relatively to the last few days where it was always between 01:00 and 02:00 am.
This day we MVPs will go deep into sessions about lots of cool new technology. Everything is under NDA, so we are not allowed to talk about it. Most of my picture will just show people and what happened over the day. There might be information out in the web, but we MVPs are not allowed to comment on that ^^

First thing of the day is to get some breakfast, which was very good in my hotel.

I tried to take the last bus at 08:30, which was not such a good idea because the bus was late 20 minutes, which leaded to getting a little late on the first meeting at 09:00. But at least I met another new nice MVP from Korea: Dong-Hoon Kim

The bus ride to Microsoft Campus was pretty quick once the bus finally arrived.

We are almost at building 92, where Studio A is just a walking distance away.

While searching for Building Studio A we went through building 92 and saw the company store right there (must have moved, last time it was somewhere completely different).

There were lots of guys and girls standing around helping us with directions.

We finally reached Studio A, pretty colorful posters up here, but finding the actual conference room was not very easy, 5000 room numbers, wtf?

Lots of XNA MVPs here.

And even more on the other side.

And some guys from the XNA team.

Dong-Hoon is also taking pictures. Funniest thing he told me yet was a joke from Korea: If someone asks you when the shuttle is coming, answer: You are not Protoss, there is no Shuttles for you.

This is Nick Gravelyn, a former XNA, which now is part of the Borg, erm, Microsoft XNA team :)

This is was happens to gramophone record here ..

XNA guys running around, I am too lazy to tag them now ..

Almost there at the new conference room location.

A big room with lots of MVPs, big meeting ahead. Sorry, not allowed to disclose any more details .. at least it was interesting stuff.

And finally walking back to the bus stop, the day is almost over. Time for a XNA party.

Kathleen explains that we will go to the Big Picture bar and whats going on in general.

On the bus ride everyone was checking and hacking on their phone. Most people have iPhones, which is kinda funny ..

We had some extra time, so like last year we visted the Game Workshop board game shop, but I don't think anyone bought anything.

The problem with the bar this time was that we were way to few people to fill it. Lots of room, but only a few guys in each. Last year this party was at this very same location, but we had some other teams here too and it was more crowded and party-like.

XNA guys like Nick talking to XNA MVPs Andy and George.

Everyone was taking pictures.

After a while the UK and Irish MVPs were suggesting that we go to the Irish pub again because there is not much going on here (even though we had Pizza and free beer, yeah). This is a quick picture from the Big Picture ^^

Some guys have their hotel right here, so they were quickly dropping of their stuff. I didn't want to go all the way to my hotel and back, so I just waited a bit here.

Don't really know how this picture happend, but from the time stamp I can see this was taken BEFORE I was even drunk, which makes not much sense. I still think this is a cool photo.

We stayed way too long in the pub, it was almost 1am when we finally left and I walked back to my hotel. At 7am my roommate got up, so there wasn't a long night sleep. Hopefully I won't be too exhausted the next day.
Today the MVP Summit actually started and I had to move from Seattle to Bellevue. Weather was pretty nice today, not really warm, but it was not raining, there was no fog and the sun was shining.

Looking outside my Seattle hotel window for the last time. Weather is pretty good tdoay.

I checked out from the Holiday Inn and took a cab to Bellevue to register for the MVP Summit and then go to my new hotel.

One last look at Seattle, good bye. I will only see Bellevue from now on and finally depart on Saturday at Seattle Airport.

Going to Bellevue means going over the big floating bridge, which is usually full of traffic. Luckily for me rush hour is over and the ride was pretty quick (otherwise it can take 30 minutes or more just to get over the bridge).

The sky was looking pretty cool out here.

The taxi driver kept talking about all kind of stuff (I better go not too much into details here, he was kinda crazy ^^). Here he was explaining to me how rich people are on average that live at this side of Bellevue.

After about 25 minutes I reached the Hyatt Hotel, where I won't be staying, but here the MVP Summit registration took place. I got my conference badge, a nice shirt, a bag and a drinking bottle. Free swag is always cool, but I heard some MVPs complaining about having too much MVP logos on the free swag sometimes ^^

I had some free time to visit some of the side sessions, but apart from a Codeplex talk there wasn't much interesting things going on. I read my emails, watched some VODs and played a little Fallout 3 on my netbook (which runs great by the way, many other games are not so good).

A quick look outside the window. Time to get to my new hotel and get some lunch ..

The weather outside was still great and I eat a baguette from Subway and ran around in Bellevue a bit.

Pretty nice area to live here, a little loud, but everything looks so new.

The buildings here and the whole downtown of Bellevue are quite new. Pretty amazing skyscrapers if you ask me:

Some shops in a fancy building.

This is still the same building ..

Okay, enough walking around. Time to go to my new hotel and meet my new roommate.

A quick view outside the window of my new room. The highway across the parking space looks really loud, but I did not hear it, neither at the day time nor at night, which was pretty cool.

And this is my new roommate Otto from Hungary. Pretty nice guy. Sorry for the bad picture.

After some relaxing and surfing via the incredible slow internet at the hotel it was time to go to the Hyatt hotel again for the MVP Summit keynote.

This is were I meet several other XNA MVPs. You can see Richard, Catalin, Andy (Z-Man) and George in this picture from back to front. I probably should have met with all the German MVPs too, but I stayed with the XNA guys all evening.

The keynote was about to start. Sorry, I cannot take any pictures from any content of this MVP Summit, everything is highly confidential and under NDA.

The keynote was kinda boring, not because of the content, but more because the speakers were a little slow and IMO there wasn't enough jokes and fun stuff sprinkeled in like in past years. After the keynotes and welcome speeches it was time to move over to the welcome area.

Lots of free beer, let the evening begin. There was also food, but I wasn't very hungry and only ate a small hamburger and some cake.

More XNA MVPs found us and the group became bigger.

Andy was telling stories as usual, but it was also great to meet up with the rest of the guys again and exchange stories and what happened over the year.

More pictures from the XNA group.

The bar was being disassembled, which isn't a good sign. Time to move to a new location. Especially the UK and Irish MVPs were suggesting going to the Irish pub on the other side of the street, which we of course did.

A quick picture from our long walk across the street.

Here you can see the UK XNA guys ready to cross the street.

We finally reached the Irish Pub and are enjoying our first beer here (additionally to the beers we had already of course).

Lots of different beers here. We tried of course several different ones.

Looking at my glass. Not a good sign ^^

An hour or two later some more XNA MVPs came by and joined us. More beer and I was already pretty drunk (I am not as trained as those other guys).

Time to go home now, it is pretty late, 8am on my europe clock, which is 11pm here.

One last look at Bellevue, I just fell into my bed once I reached the hotel. The next day my head was brumming a little, but I guess I still had a good night sleep, which was very much required.
The last thing I recorded this day was this police car at night:
A fellow MVP Patrick Smacchia is the developer of the .NET tool NDepend, which allows to analyze any .NET code base and helps dealing with code complexity. Since I have been using the tool on and off for a while now and recently very much for the development of our new Engine (a multiplatform engine in .NET), I was asked to write a little review about it. Why not, it is a great tool :) NDepend is probably most recognized for generating interesting looking Bubble Graph. For example our current early testing engine produces the following graph. This tells us where we need to refactor the most, simplify stuff, add more features, etc. Please note that we are currently heavily editing the engine every day and this graph changes almost completely every week. This Bubble Graph shows which methods in all of our 32 projects are currently public (blue). As you can see maybe the Helpers assembly on the left is mostly gray because we already made lots of stuff private/protected. This is just one example, there are many many metrics that can be displayed. 
After extracting NDepend (there is no installer) you have a bunch of files in some directory. The most useful looking one is VisualNDepend.exe, which starts the GUI of NDepend. As you can see you can enable integration with Visual Studio 2005 and 2008 (no 2010 yet, but does not really matter, you can still start NDepend by yourself) and with the great Reflector tool. The integration via the addins just provides an easier way to load and inspect assemblies, you can do the same with Visual NDepend on your own.  The second thing I noticed was the "Getting Started" panel, which provides a great deal of help and especially tutorials on how to do things. This is kinda important for NDepend because it is not clear what you actually do with this tool, even after using it for a while. The bad thing about all the tutorials (all of them can be found online: http://www.ndepend.com/Features.aspx) is that they have no sound or voice, just boring text boxes popping up. But if you search for a feature or want to know how to do things, you will most likely find some useful information after a very short while. Also good is that all the information can be found at a central location and everything is linked nicely together. After using the tool a few times it is also not that hard to write own commands with the CQL (Code Query Language) inside NDepend, which is pretty much self explanatory and can be written very easily with Intellisense, for example: SELECT METHODS WHERE NbLinesOfCode > 50 AND IsPublic This selects all public methods with more than 50 lines of code in the Bubble Graph. Since only a handful methods will popup (in blue), it is easy to now go and refactor those methods if we really want to reduce the complexity of methods that have too many lines of code. You can obviously show many other things with NDepend, but I usually just go to the Features page or play around with the dropdownbox values until I find something that looks interesting for my assemblies (lines of code, il instructions, complexity, accessors, number of callers, etc.). Then on our "Refactoring Friday" we can use this data to make more clever decissions and refactor methods that really need refactoring and are actually used instead of refactoring anything that is not called much anyway and we should not care much about yet anyway.
VisualNDepend also shows some other interesting metrics. The Dependency Graph shows which assembly is required by which assembly and what assemblies they use in turn (until reaching mscorlib on the right usually). The cool thing is when investigating some assembly, e.g. in the Dependency Matrix, it will also be highlighted in the other views (e.g. Dependency Graph or the Bubble Graph in Metrics). The following image shows which assemblies are using Delta.Helpers and which assemblies it requires itself. Please note that most assembly loading happens dynamically in our engine, which NDepend does not show, so this is only partially useful for us. But for some rules, like every assembly should reference our base assembly Delta, we can easily check if any assembly does not follow this rule by hovering the mouse over Delta, which will highlight all assemblies that use it, the rest remains gray.  One final image I want to share is the Dependency Matrix, which shows which assembly is used by which other assembly. Since most assembly and type usage happens dynamically at load time, most of this matrix should be empty. As you can see some assemblies still have quite a lot of references. For some it makes sense because it it can be easier to use Utilities statically instead of defining an interface for every freaking method. This is why we have a few exceptions for static modules, which have almost no other assembly requirements, but are used by many assemblies. It is still easy to replace such assemblies, but they cannot be replaced at runtime like our dynamic modules. I will blog more about this in the future. For now NDepend helps us to see that some assemblies still have too many static references and others are ok. Next Friday we will focus and removing some more references in those assemblies, which still have too many dependencies we do not want. Until then the Dependency Matrix will probably look pretty much like this (more modules are coming and going every day however): 
In the last few weeks i was reading many articles about writing games on different platforms. Each platform has their own frameworks, restrictions and so on. As C# is my main programming language i want to talk a bit about writing C# games on multiple platforms. Platforms: - Windows – one of the most established platforms is and will be windows with DirectX. Since XNA is out creating games for windows is easy as pie and everything is based on C#. - XBox 360 – Same as windows this platform can be programmed with XNA and C#. So very simple. Problem for hobby developers is that you need a Creators Club Premium Membership to test your games on the Xbox. - Linux – now a very unusual gaming platform but very easy to program! Using the mono framework C# code can be run on unix based systems e.g. Linux or Mac. For OpenGL graphics we can use the OpenTK framework which runs very well with mono. - Zune/Zune HD – a very new platform is the microsoft zune. But it’s also easy cause XNA supports this platform as well. - iPod Touch/iPhone – these are not that easy but important cause the apps you can buy on the internet are selling very well. The problem is that apps for these two platforms are normally written in objective-c and it’s more ugly than c++ in comparison to C#. Cause of this a new framework came up called MonoTouch. Okay this makes it possible to run C# code on the iPhone and you also get a special version of OpenTK with it but it only compiles on Mac. That makes it very hard to create and build your games on windows. You can write a little tool which sends the code to another tool on the mac which compiles it and sends it back but this is very time consuming and ugly. Hope there will be an other way soon! In addition you must be aware of that OpenTK for iPhone and MonoTouch is very new so many stuff is still missing. Not tested: I never tested this but i was reading about it that you can run C# games on Wii and Android with mono as well. Hope i can test this sometimes in the future. Interesting links: - C# on Android, iPhone and Wii with mono - OpenTK Documentation - Mono Documentation - MonoTouch Trial version Hope these short introductions helped you a bit exploring new and interesting platforms  Regards

We recently had the problem that we want to share some structs we wrote with other structs in other assemblies. For example we cannot change XNA Vector3 (well, its not open source) and even an open source Vector3 like the one from OpenTK should not be changed, we just want to use the libraries. However, if you start using an XNA Vector in some class and then decide you want to switch to OpenTK, you kinda have a problem. The data is EXACTLY the same: X, Y and Z, thats it! Just 3 floats, but many different structs that describe them and have different methods for manipulating them. If you are only using XNA or only OpenTK, then there is no problem, except maybe when you want to extend the given Vector3 struct from the framework/library you are using. Then you might introduce a Vector3Helper class like I did in almost all my XNA projects, which is kinda ugly too. Our engine however is going to support many frameworks and libraries, and not only that, it is easily extensible and totally customizable. We do not enforce to use XNA or OpenTK or whatever else, it is all a choice of the programmer, whatever he needs. To accomplish this I today present a very little cute trick on how to merge all those structs together and make them easily extensible: Yes, you can add methods to exsting structs without any helper classes!
The magic word is: Union. Now you might say: Wait a second, C++ has unions, but C# does not have them and using pointers is also no fun in C#. Well, you still can use the StructLayout(LayoutKind.Explicit) attribute and then the FieldOffset(0) attribute to mark overlapping memory regions. Just add all the structs (since they are value types and have the sequential x, y, z data there are all the same) and then define x, y and z yourself and use whatever vector you want. Our implementation works a little different because the use of XNA or OpenTK is optional (Tip: Did you know that you can have partial structs? They are fun ^^), but the overall idea is very much the same. I present you the Vector3 struct with XNA and OpenTK support all in one:
///
/// Class with own Vector3 functionality, but still using the same shared
/// memory as Vector3 does. This not only means we get all the XNA Vector3
/// (and any other Vector3 we plug in here) functionality for free, but
/// we can also mix the data types as much as we want (e.g. just set
/// the xnaVector and all the other vectors are set automatically for us).
///
[StructLayout(LayoutKind.Explicit)]
public struct Vector3
{
#region Shared vectors (XNA, OpenTK, and our own data)
// First setup the shared vector structs. Start with an XNA Vector.
// Note: This could also be private if you want to hide this from the
// Vector3 users!
[FieldOffset(0)]
public Microsoft.Xna.Framework.Vector3 xnaVector;
// Same with OpenTK.Vector3
[FieldOffset(0)]
public OpenTK.Vector3 openTkVector;
// And then the same data again just as we want to use it! Start with x.
[FieldOffset(0)]
public float x;
// Da Y coordinate
[FieldOffset(4)]
public float y;
// And finally the z coordinate!
[FieldOffset(8)]
public float z;
//Note: This won't work, it would make x, y AND z all start at offset 0!
//[FieldOffset(0)]
//public float x, y, z;
#endregion
// Go ahead with our constructors, methods, etc.
// Note: We can easily use the XNA or OpenTK functionality here.
} // struct Vector3
And finally some testing code to prove this actually works (this is just some copied code from our early unit tests, I just added some Console.WriteLine code lines):
// Create a simple vector that happend to have the length 5 (3*3+4*4=25)
Vector3 vector = new Vector3 { x = 0, y = 3, z = 4 };
Console.WriteLine("vector=" + vector);
Console.WriteLine("vector.x=" + vector.x);
Console.WriteLine("vector.y=" + vector.y);
Console.WriteLine("vector.z=" + vector.z);
// Sadly xnaVector and vector are not the same by default :(
// We could easily add operators to support comparing these too,
// but for now we should try to use Vector3 exclusively.
//does not compile: Assert.Equal(vector, vector.xnaVector);
Console.WriteLine("XNA vector=" + vector.xnaVector);
Console.WriteLine("OpenTK vector=" + vector.xnaVector);
// Lets play around with xnaVector and openTkVector
// First use an XNA method
//Assert.Equal(5, vector.xnaVector.Length());
Console.WriteLine("XNA vector length=" + vector.xnaVector.Length());
// Next try an OpenTK method
//Assert.Equal(5, vector.openTkVector.Length);
Console.WriteLine("OpenTK vector length=" + vector.openTkVector.Length);
// Do a more complicated test, add another XNA vector and then
// check if the OpenTK vector is also updated.
Vector3 anotherVector = new Vector3 { x = 0, y = 3, z = -4 };
// Note: We don't have our own + operator yet, just use the one from XNA
vector.xnaVector += anotherVector.xnaVector;
// Finally check if our new vector is 0, 6, 0 now!
Console.WriteLine("XNA vector+anotherVector=" + vector.xnaVector);
Console.WriteLine("OpenTK vector+another length=" +
vector.openTkVector.Length);

Buyaa, I'm Microsoft MVP once again in the XNA/DirectX category for one more year (2009/2010). I have been an XNA MVP since 2006 and I'm still very proud of it :) I was pretty busy this year with our current game project "Fireburst" at exDream (a racing game for Xbox 360, PS3 and PC using the Unreal3 engine, more about it soon) and theirfore I did not do many other things (except writing some iPhone games, starting to develop my own dynamic language and some tools). But once that project is done in 1-2 months, I will do lots more XNA fun stuff and hopefully XNA Community Games (now called Indie Games on the Xbox 360, I really hate that term) will be available in Germany so I can finally review and submit some games myself. I'm still pretty fit in XNA 3.1 and DirectX 11 (played around with it a lot in March), but for XNA I'm still waiting for availablilty in Germany and for DirectX 11 I'm really waiting for some cool hardware at the end of this year. At exDream we recently also had some interesting discussions about using .NET for PS3 (recently possible thanks to Novell), Xbox 360 (hello XNA) and PC or even more dynamic script languages for upcoming projects. Maybe also including some other promising platforms such as iPhone (also .NET able thanks to Unity), Android, PSP Go, WII, whatever, but that all should depend more on the game and if we are able to manage so many platforms. Working with XNA was almost no extra work to make a game run on the Xbox 360 plus the PC, the game just has to fit and you obviously should allow control with the Xbox 360 controller. Our multiplatform game Fireburst is also not that bad to develop for because most issues are handled by the great Unreal3 engine (except the fact of course that it is all ugly C++ and UnrealScript code, which just looks like C++ anyway and even has to be compiled), but it is still quite a lot more work than just doing a PC only game, especially because of optimizations and testing required for all platforms. Enough rambling, I'm going to celebrate this day by installing Windows 2008 server (omg) because our pre-release version we had on there just ran out (warg) .. stupid thing has to be completely reinstalled, no upgrade option ..
Today I had a discussion with a few other programmers (Hi ViperDK and Timo ^^) about foreach and for loop performance. Everyone had his own ideas and experiences, but we talked mostly about XNA on the Xbox 360 (using the compact framework, that does not like foreach, just use for all the time in tight render loops for your XNA games, foreach will create too much IEnumerator garbage that will not be collected) or other special cases (huge arrays or lists). Anyway, just guessing around is obviously not as good as actually writing a performance test application and see whats going on (see end of this article for download link). Again, we need a disclaimer: You will probably never write loops with 1 billion iterations, these numbers are similar for less iterations, but you should always try to write clean code and ONLY optimize when it is required after finding performance issues! Lets go directly to the results for 1 billion for or foreach iterations in release mode (will loop through a 10k array or list for 100k times, see below for code):  As you can see there are some major differences between using foreach with an array or using a generic list (boxing/unboxing is not the issue here, you would not be able to archive this performance with an ArrayList). Another thing you can notice right away is that using simple arrays is always faster than using dynamic lists, even converting them from a list to an array via .ToArray() and then executing the foreach is much faster. It also makes a HUGE difference executing this in debug mode (I execute my code almost 99% in debug mode), everything is 4 times slower for this special performance test. Except for Foreach+List, which is in comparison not that bad in debug mode. What is really bad is For+List, which almost takes 16 seconds to execute 1 billion times (again using my Core 2 Duo 6600 CPU with 4 GB Ram).  Thanks to some helper methods the code for this performance test is pretty short and easy (check end of this article for the source code download link): Stopwatch timer = new Stopwatch();
// Run through all tests
for (int test = 0; test < 8; test++)
{
// Find out which test we wanna make
bool rememberLength = (test / 4) % 2 == 1;
bool useForeach = (test / 2) % 2 == 1;
bool useList = test % 2 == 1;
// Start timer for test
timer.Start();
// Execute
int result = RunForOrForeachLoops(rememberLength, useForeach, useList);
// Stop timer
timer.Stop();
// Skip this test if we got no result!
if (result == 0)
continue;
// Report results!
resultText = ...
Console.WriteLine(resultText + ": " + timer.ElapsedMilliseconds + "ms");
// Reset timer for next run
timer.Reset();
} // for
The interesting code obviously happens in RunForOrForeachLoops. It basically executes the 1 billion iterations in several different ways (8 ways, as you can guess by the for main test for loop). All of those produce the same result, half of the tests use int[] intArray, the other half uses List<int> intList. And again half of the tests uses just for loops, the other half uses foreach for the iterations. Lets examine the useForeach=true and rememberLength=false cases (btw: Iterations is 100000 and the intList and intArrays have a size of 10000 elements):
if (useForeach)
{
if (useList)
{
for (int iter = 0; iter < Iterations; iter++)
{
result = 0;
foreach (int val in intList)
result += val;
} // for
} // if
else
{
for (int iter = 0; iter < Iterations; iter++)
{
result = 0;
foreach (int val in intArray)
result += val;
} // for
} // else
} // if
else // useForeach == false
...
To figure out the differences between those few lines of code in RunForOrForeachLoops, that almost look the same, we have go to IL code once again. First lets check out what the fastest code block Foreach+Array is being compiled to in IL: result = 0;
foreach (int val in intArray)
result += val; This becomes in IL: L_0007: ldsfld int32[] TestSimpleForeachApp.Program::intArray
L_000c: stloc.2
L_000d: ldc.i4.0
L_000e: stloc.3
L_000f: br.s L_001d
L_0011: ldloc.2
L_0012: ldloc.3
L_0013: ldelem.i4
L_0014: stloc.1
L_0015: ldloc.0
L_0016: ldloc.1
L_0017: add
L_0018: stloc.0
L_0019: ldloc.3
L_001a: ldc.i4.1
L_001b: add
L_001c: stloc.3
L_001d: ldloc.3
L_001e: ldloc.2
L_001f: ldlen
L_0020: conv.i4
L_0021: blt.s L_0011
In L_0021 we jump up to L_0011 as long as we are not done with the loop yet. Inside all the result += val happens, but we do not see any slow code, there are no calls to any methods, there is no unboxing and this all can probably be executed quickly after being complied to assembler by the JIT (just-in-time) compiler. On the other hand, if we look at pretty much the same code, just with intList instead of intArray, the whole story changes: result = 0;
foreach (int val in intList)
result += val; becomes much more complex IL code with lots of function calls, the creation of an Enumerator and there is even a dispose at the end (hello GC): L_0007: ldsfld class [mscorlib]System.Collections.Generic.List`1<int32> TestSimpleForeachApp.Program::intList
L_000c: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
L_0011: stloc.2
L_0012: br.s L_0020
L_0014: ldloca.s CS$5$0000
L_0016: call instance !0 [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
L_001b: stloc.1
L_001c: ldloc.0
L_001d: ldloc.1
L_001e: add
L_001f: stloc.0
L_0020: ldloca.s CS$5$0000
L_0022: call instance bool [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
L_0027: brtrue.s L_0014
L_0029: leave.s L_0039
L_002b: ldloca.s CS$5$0000
L_002d: constrained [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
L_0033: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_0038: endfinally
What even looks worst too me is the code that is executed in MoveNext (get_Current just returns this.current, no extra instructions here). Since the IL code is very long and confusing (31 IL instructions), here is the C# code of MoveNext: public bool MoveNext()
{
List<T> list = this.list;
if ((this.version == list._version) && (this.index < list._size))
{
this.current = list._items[this.index];
this.index++;
return true;
}
return this.MoveNextRare();
}
And MoveNextRare could also be called at the end of MoveNext if something changes for the list (not the case in our example). But we have to keep in mind that this is just IL code, not actual code that will be executed on the CPU. The JIT compiler can still optimize things out, which we won't see here. But something must be going on since Foreach+List is definiately slower than using all the other approaches to get through all the values in intList. I recommend Foreach+Array converted from List because the IL for Foreach+Array is really fast and does not use any extra methods or Enumerators, especially if you know that the array won't change much and if you do not have to call .ToArray every time when you do a foreach. And here is the sample project for all this performance testing fun:
|
|
|