![]() |
| [[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]] |
|
|
#1 |
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
Hi all,
Let me start with a famous qoute from Butler Lampson: "All problems in computer science can be solved by another level of indirection". This is quite true when building complex systems and forms the basis of abstraction. Unfortunately, when performance and memory usage are of primary concern his words often have to be appended with: "Except the problem of having too many levels of indirection"... One such situations is a (Pascal) string class. To create variable-length strings with an explicit size field (for fast processing), we would normally start with something like this: Code:
What we really want is the string to follow directly after the 'size' field. That way there would be no extra pointer dereferencing, and it can be one allocation with just 2 bytes extra. This can be achieved with placement new. Placement new takes an extra parameter, the pre-allocated memory location where to construct the object: Code:
So I hope this inspires you to create more efficient data structures too. One word of caution though: don't blindly apply this trick. Profile before you optimize! Cheers, Nicolas (*) Assuming a 32-bit environment. It's even worse with 64-bit... Last edited by Nick : 11-25-2007 at 04:28 AM. |
|
|
|
|
|
#2 |
|
DevMaster Staff
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
|
Nice trick, but shouldn't the factory function be static?
___________________________________________
Currently working at Sucker Punch reedbeta.com - OpenGL demos and other projects Luabridge - a lightweight, dependency-free C++/Lua binding library. CD Lite - an unobtrusive, minimal CD player application for Windows. |
|
|
|
|
|
#3 |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Why not create a placement new that takes the size of the string?
Code:
Code:
Basically generates the same code as your version, but the user doesn't have the burdon of the implementation details like the placement new and such. It can simply use the PascalString object like any other.
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. |
|
|
|
|
|
#4 |
|
DevMaster Staff
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
|
.oisyn, doesn't your second version defeat Nick's stated purpose (which was to remove an indirection)?
___________________________________________
Currently working at Sucker Punch reedbeta.com - OpenGL demos and other projects Luabridge - a lightweight, dependency-free C++/Lua binding library. CD Lite - an unobtrusive, minimal CD player application for Windows. |
|
|
|
|
|
#5 | |
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
Quote:
|
|
|
|
|
|
|
#6 |
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
.oisyn, thanks for the stack version! As Reedbeta noticed though, it defeats the purpose when allocating strings on the heap.
I don't think it's possible to combine both and keep all benefits, but I'd love to be proven wrong. Anyway, this trick is really about being aware of the relationship between indirections and performance. It's only useful for very specific bottlenecks, and the objects will likely be on the heap. In case they're on the stack your solution would be preferable though. |
|
|
|
|
|
#7 | |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Quote:
) a bit easier.
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. Last edited by .oisyn : 11-25-2007 at 09:33 AM. |
|
|
|
|
|
|
#8 | |
|
New Member
Join Date: Aug 2005
Posts: 5
|
Hey Nick,
I like the gem, simple but I can see how this could make a big difference in some situations. Are there any issues with respect to portability, or other subtle gotchas to be aware of? Quote:
The gem really targets the situation where the objects have to be allocated dynamically. If you're going to put them on the stack then you may as well use the very first implementation with size and string pointer both as data members. Thomas |
|
|
|
|
|
|
#9 |
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Argh! Is it me or are you simply not getting what I'm saying? I'M NOT PUTTING THE WHOLE STRING ON THE STACK, I SIMPLY SUGGEST CREATING A WRAPPER FOR THE POINTER TO MAKE THE USAGE EASIER AND SAFER!!! Geez...
There is absolutely no difference between a single pointer and an object containing a single pointer. Whichever one you use, there is no other way than putting it on the stack.
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. Last edited by .oisyn : 11-26-2007 at 04:11 AM. |
|
|
|
|
|
#10 | |
|
New Member
Join Date: Aug 2005
Posts: 5
|
Quote:
Hmm.. so I guess you're saying that where Nick might have something like: std::list<PascalStringWithPlacementNewTrick*> you would look to replace this with something like: std::list<PascalStringWithPlacementNewTrickPointer > ? I guess that is then preferrable to: std::list<OriginalPascalStringWithSizeAndPointerMe mbers> because, for example, copying the list doesn't have to move around so much data and so on, even if accessing the actual string data through this list involves exactly the same number of indirections.. btw. Your user gif fits really nicely with the text of that last message. ![]() |
|
|
|
|
|
|
#11 | ||
|
DevMaster Staff
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
|
Quote:
. And the code generated for these template instantiations would probably even be binary identical.Quote:
![]()
___________________________________________
C++ addict - Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3. |
||
|
|
|
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
|