Is this true?
My game will be so simple that the performance will not really matter. I'm doing this for the programming experience.
Just to get a nit-pick out of the way first, the library you're talking about is not the STL, it's the C++ Standard Library -- although the former term is so often used as to make them almost interchangeable, and you'll likely never run into a situation where it leads to confusion.
As to your actual question, my recommendation would be that implementing your own containers and algorithms can be a great learning experience, and one that every programmer would benefit from tackling at some point, but that you should then go right back to using the well-tested and very capable versions provided by the standard library in your actual code.
Yes, it is true that the standard library (or parts thereof) are not always used in professional development. This is due to a number of reasons, and some of the valid ones include lack of a good implementation (or any implementation) for a particular target platform and performance concerns. Some of the invalid ones include NIH syndrome, inexperienced programmers, or acting on rumoured poor performance without actually testing the suitability for their own usage. Writing and using your own versions when those good reasons don't apply to you likely won't provide a particularly valuable experience however.
Some other reasons I recommend using the standard library:
-It's standard, and therefore (if used appropriately) clearly communicates the intentions and usage of your code to other programmers. Other programmers will be experienced with these containers and be able to follow your code without having to examine the implementations of your containers or algorithms.
-The performance concerns are often over-stated, and unless you know they actually apply to your situation and have the experience to write a good alternative you probably won't get any benefit. Using the standard library extensively may also allow you to get a good grip on what limitations do actually exist.
-Some studios do use the standard library, and it's also valuable in non-games programming.
-Some studios will improve the standard library's performance (by providing custom allocators, etc.) rather than rolling their own version, in which case your experience would remain relevant.
-Making use of the standard library will more easily allow you to finish your own bug-free and acceptably performant projects in a reasonably amount of time -- would you prefer a portfolio with a number of polished and bug-free games, or with a lesser number of potentially buggy games that use your own implementations?
-Some studios will use their own implementations, such as EASTL for example. Given these libraries are quite often intended as replacements for the standard library, experience with using the standard library will give you an excellent starting point for being able to quickly learn the proper usage of these alternatives if necessary.
TL;DR:
Write your own versions as an educational experience, but use the standard library in your actual projects.
Hope that's helpful! ![]()
typedef std::vector<Unit> UnitArray;
typedef MyVector<Unit> UnitArray;
I heard that the STL is too slow for use in a high-performance game.
[/quote]
Any performance issues that AAA companies find with the Standard C++ Library is that it's general nature doesn't allow them to do certain things. For instance, there isn't a way to tell std::vector<> to use a given piece of memory easily. The "allocator" parameter for standard library templates are a little underbaked and often don't give enough control to the client programmer.
Thus, the problems are of a design nature, not the actual implementation. The implementation of the standard containers tends to be very high quality. Most programmers are not going to beat the performance of classes like std::vector if they stick to the interface it outlines. In fact, many underexperienced programmers are likely to produce code that is algorithmically poorer, and thus will suffer heavily in real use.
I've been told that if you want to use the same coding techniques as a AAA game, you have to make custom classes...
[/quote]
It makes no sense to apply the "coding techniques" of a massive, professional team to your small personal projects.
... your linked lists, trees, etc., rather than just using LinkedList<MyClass> (or whatever the STL syntax is).
[/quote]
If you're worried about performance, you should strongly consider not using linked lists at all. They are almost always going to be slower than dynamic arrays on modern machines with real data.
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][background=rgb(250, 251, 252)]I'm doing this for the programming experience.[/background]
[/font]
[/quote]
I believe there is great value in implementing the standard containers yourself, as a learning exercise, in particular if you have a reliable source to get some feedback from. However, I would not recommend using such an implementation for a real project.
If you're worried about performance, you should strongly consider not using linked lists at all. They are almost always going to be slower than dynamic arrays on modern machines with real data.
[background=rgb(250, 251, 252)]If you need to insert or remove items somewhere in the middle instead of just at the end (vector) or at the beginning or the end (deque) a linked list it practically guaranteed to be faster.[/background]
[/quote]
It depends. If the order is irrelevant, "swap and pop" is very fast.
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]
[background=rgb(250, 251, 252)]Use the proper container for a given algorithm, taking into account the algorithmic performance (in this case O(1) vs O(n) insertion).[/background][/font]
[/quote]
The cache performance, not the algorithmic performance, dominates modern hardware. Jumping around memory using a linked list is worst case behaviour from the cache's perspective. Algorithmic analysis assumes that accessing memory costs the same regardless of how it is done.
In most real programs, insertions and deletions are "rare" and iteration is common. Speeding up insertion and deletion, while making iteration slower, will often have a much larger cost in the long run. When the data set is small, the performance implications of copying it all around is negligable. When the data set gets large, cache tends to dominate.
This blog post quotes a slide from Bjarne Stroustroup illustrating some of these ideas. Unfortunately the code isn't included and I have no time to search for it now.
Again, this is a general rule but not absolute. I used the qualifying terms "real program" and "almost always" for a reason. There are sweet spots where linked lists make more sense. In particular, linked lists have a (more or less) stable running speeds, while vector only has amortised running speed, with potentially large spikes around reallocations and deletions. Though linked lists aren't immune to spikes. Carefully loaded linked lists might behave nicely with the cache, but the "wrong" set of insertions and deletions might radically change their performance profile.
It depends. If the order is irrelevant, "swap and pop" is very fast.
The cache performance, not the algorithmic performance, dominates modern hardware. Jumping around memory using a linked list is worst case behaviour from the cache's perspective. Algorithmic analysis assumes that accessing memory costs the same regardless of how it is done.
The cache performance, not the algorithmic performance, dominates modern hardware. Jumping around memory using a linked list is worst case behaviour from the cache's perspective. Algorithmic analysis assumes that accessing memory costs the same regardless of how it is done.QFE. This is why designing your data-structures to fit into compact blobs of bytes is so important.
char* data = (char*)malloc(640*1024);//640KiB should be enough for anybody
vector<Foo,42>& fooVec = *new(data) vector<Foo,42>();
data += sizeof(fooVec);I don't think anyone would disagree that vectors would be used more often, but the argument is that there are still real world cases where linked lists are better for performance. In some cases, order is important, for example.
The cache performance, not the algorithmic performance, dominates modern hardware. Jumping around memory using a linked list is worst case behaviour from the cache's perspective. Algorithmic analysis assumes that accessing memory costs the same regardless of how it is done.
In most real programs, insertions and deletions are "rare" and iteration is common. Speeding up insertion and deletion, while making iteration slower, will often have a much larger cost in the long run. When the data set is small, the performance implications of copying it all around is negligable. When the data set gets large, cache tends to dominate.
This blog post quotes a slide from Bjarne Stroustroup illustrating some of these ideas. Unfortunately the code isn't included and I have no time to search for it now.[/quote]But this is a case that also includes the time to search linearly for the insertion point. It also only shows a single insertion/deletion AFAICT - what about an algorithm with a large number of insertions?
Again, this is a general rule but not absolute. I used the qualifying terms "real program" and "almost always" for a reason. There are sweet spots where linked lists make more sense.[/quote]Yes, I think this is the pointYour original posts said one should not use lists at all, not that vectors are usually better.
(Also there are cases where neither make a difference for performance, but using a list fits better with writing readable code due to the nature of the performance, so using a vector in some belief that it'll be faster is just premature optimisation.)
The above is the reason game engine dev's might avoid STL containers - because the STL enforces the interface of random new/delete calls on your memory allocator. You can supply custom allocators to the STL, but they have to follow it's interface.
[quote name='Hodgman' timestamp='1337003402' post='4940069']The above is the reason game engine dev's might avoid STL containers - because the STL enforces the interface of random new/delete calls on your memory allocator. You can supply custom allocators to the STL, but they have to follow it's interface.The interface allows for enough flexibility in most cases. E.g. pooled allocators etc. should all be possible.[/quote]In most cases for whom? I do actually agree with that sentence, for most people, but when talking about high-performance game engines, "general purpose" allocation (i.e. new/delete) is entirely inadequate for a lot of purposes. For starters it's a singleton, which is asking for trouble...
Since we are already on the topic of cache coherence: Instead of arrays of compact structs, structs of arrays can be even better. And for optimal performance you may need arrays of structures of arrays... caches are a bitch ;)And lists and maps and trees too... as long as they're designed to fit in the constraints.
The interface allows for enough flexibility in most cases. E.g. pooled allocators etc. should all be possible.[/quote]
STL doesn't allow for pooled allocators due to underspecified allocator semantics. It works for specific implementations and code will be fully standard-compliant, but will mysteriously break on some compilers.
STL basically says: valid implementation may be stateful or stateless.
Linked lists in practice also suffer from another problem - search. There are two cases:
- iteration/additions/removal dominate - GC-collected vector wins
- search dominates - map/hashmap wins
Even for things like browser DOM or UI in general, one will frequently search for a group of objects fitting a criteria, requiring full sweep over entire structure with multiple results or operations.
Linked lists make sense only when the cost of copying is disproportionate to other operations or where reallocation cannot be performed at all, such as disk-based data or things like URL. In all other cases they lose even at algorithmic level. And even in these cases, bulk operations are often used (b-tree or other form of pre-computed index, sitemaps for web sites).
QFE. This is why designing your data-structures to fit into compact blobs of bytes is so important.
[quote name='rip-off' timestamp='1337002061' post='4940057']The cache performance, not the algorithmic performance, dominates modern hardware. Jumping around memory using a linked list is worst case behaviour from the cache's perspective. Algorithmic analysis assumes that accessing memory costs the same regardless of how it is done.
char* data = (char*)malloc(640*1024);//640KiB should be enough for anybody
vector<Foo,42>& fooVec = *new(data) vector<Foo,42>();
data += sizeof(fooVec);This topic has been locked by a moderator. New replies are not allowed.
With your permission, GameDev.net uses analytics cookies to understand how people use the platform. You can accept analytics or continue with necessary cookies only. Learn more