Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

TLDR: using typeof(T) twice; assigning the value to a variable and reusing that = uber fast (30FPS), actually calling typeof(T) twice = derped (5FPS). Why?


I have a simple entity/component system; my basic entity had an array of IComponents, and methods like HasComponent<T> and GetComponent<T>. These just iterate over the arrays and return the first matching item (this.components.Any(c => c is T)).

Turns out a performance bottleneck I experience with 100k components "in memory" (albeit most off-screen) is actually these two methods. With a few components, no problem (30FPS+). With 100k components, just sprites, I get around 5FPS.

So I figured, why not use a Dictionary<Type, IComponent> instead? It'll be faster, right?

Right?!

Wrong. First, a complexity: I have a SpriteComponent class, and a SpriteSheetComponent component class (knows about frames, animation, etc.). To simplify everything, SpriteSheetComponent derives from SpriteComponent. This makes drawing, ordering, etc. simpler, because of the is-a relationship.

Second, querying for components became more complex; if I ask HasComponent<SpriteComponent>, and you have a SpriteSheetComponent, you should return true, right?

So the way I handle that is:

return this.components.Keys.Any(t => t == typeof(T) || t.IsSubclassOf(typeof(T)));

Ditto for fetching the element, except I use First instead of Any.

Anyway, I noticed that the performance actually degraded. What's even more surprising is that this fixed the performance issue:

var tType = typeof(T);
return this.components.Keys.Any(t => t == tType || t.IsSubclassOf(tType));

The only difference is that I'm checking typeof(T) once and reusing that. This fixed my FPS up to 30ish, hurrah.

But this is definitely a "lolwut" moment for me. Is typeof(T) really that slow? And in this case, it's shredding my performance with just one extra call?

share|improve this question
4  
This is probably more of a Stackoverflow question. In fact, I found an answer for it here: stackoverflow.com/questions/6417763/… and dotnerperls also has a bit to say on it: dotnetperls.com/typeof How many of these comparisons are you doing per frame? –  michael.bartnett Dec 22 '12 at 5:16
    
Honestly, I'd consider typeof to be a red flag function, you probably call it because you have made a mess of your data structure. If you had a clean design the type would either be implicit in the code, or the difference would be handled by the objects's own methods. –  eBusiness Dec 22 '12 at 13:00
    
@eBusiness getting components by type from a generic container is, as far as I know, a standard solution to designing your entity system. –  ashes999 Dec 22 '12 at 16:38
1  
@ashes999 I recognize that you have been particularly unlucky, and even with the given explanations I fail to understand why typeof would be that slow. That you are paying in speed for using a generic container is however no surprise. The thing is, you are probably also paying in some combination of code complexity, readability, and debugability. The key question is, if you want to treat the objects differently, why do you put them on the same list in the first place? –  eBusiness Dec 22 '12 at 19:00
add comment

1 Answer

up vote 11 down vote accepted

Well, it's not really one extra call, is it? It's n * 100k extra calls per frame, if you're doing this every time you retrieve the sprite component for each entity!

Maybe your entity should just have a field for the sprite component, null if it hasn't got one, rather than indirecting through all this dictionary and typeof stuff. Ditto for other commonly used components.

I understand the impluse to generalize, but your system sounds rather overengineered for what it needs to do.

BTW, if you have 100k entities (a huge number by most game standards) and most of them are offscreen, you should definitely invest in a space-partitioning system of some sort so you can avoid updating - or even looping over - all of 'em.

share|improve this answer
    
I actually do have a spatial partitioning scheme already (quad tree). I'm selectively drawing what's on-screen only. The problem is, these are just map tiles -- I can't even keep a 100x100 map in memory and draw some of it on screen. Maybe pulling out the sprite component makes more sense. –  ashes999 Dec 22 '12 at 13:09
    
I started adding straight sprite components instead of adding them as entities and the issues seems somewhat resolved. Cheers. –  ashes999 Dec 22 '12 at 16:38
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.