Sign in to follow this  
Laval B

64 bits integer on 32 bits applications

Recommended Posts

Hello all.

I was looking at this very lite implementation of a handle manager [url="http://gamesfromwithin.com/managing-data-relationships"]here[/url] where many fields are packed into a single 32 bits integer (as bit ranges). This implementation is used for very small games on small machines though which makes 32 bits enough. However, if i want to use that design for managing a much bigger amount of resources, i will have to either use more then one handle managers like this one (really not great) or use a 64 bits integer handle to have "wider" bit fields.

So my question is this : is there a big overhead using 64 bits integers on a 32 bits architecture (like x86) ?

Share this post


Link to post
Share on other sites
[quote name='alvaro' timestamp='1318795460' post='4873201']
It depends on what you want to do with them. For the bitwise operations you are likely to use in this case, it should be just fine.
[/quote]




The manager is basically an array of struct HandleEntry defined like the following :

[code]

struct HandleEntry
{
HandleEntry();
explicit HandleEntry(uint32 nextFreeIndex);

uint32 m_nextFreeIndex : 12;
uint32 m_counter : 15;
uint32 m_active : 1;
uint32 m_endOfList : 1;
void* m_entry;
};
[/code]


and it has methods to acces it that work like those

[code]


void* HandleManager::Get(Handle handle) const
{
void* p = NULL;
if (!Get(handle, p))
return NULL;
return p;
}



bool HandleManager::Get(const Handle handle, void*& out) const
{
const int index = handle.m_index;
if (m_entries[index].m_counter != handle.m_counter ||
m_entries[index].m_active == false)
return false;

out = m_entries[index].m_entry;
return true;
}


template< typename T >
inline bool HandleManager::GetAs(Handle handle, T& out) const
{
void* outAsVoid;
const bool rv = Get(handle, outAsVoid);
out = union_cast< T >(outAsVoid);

return rv;
}
[/code]


Where Handle is defined like

[code]

struct Handle
{
Handle() : m_index(0), m_counter(0), m_type(0)
{}

Handle(uint32 index, uint32 counter, uint32 type)
: m_index(index), m_counter(counter), m_type(type)
{}

inline operator uint32() const;

uint32 m_index : 12;
uint32 m_counter : 15;
uint32 m_type : 5;
};
[/code]



What worries me the most is the union_cast. I guess l'ill compile the example in release and take a look at the generated assembly. I know a 64 bits integer will take two registers on 32 bits architecture.

Share this post


Link to post
Share on other sites
It looks to me like that union_cast has nothing to do with the bitfield - m_Entry is just a normal void* pointer.

Also note that you can have more than 32-bits worth of values in a bitfield without using 64-bit types. For example try this:

[code]struct HandleEntry
{
HandleEntry();
explicit HandleEntry(uint32 nextFreeIndex);

uint32 m_nextFreeIndex : 24;
uint32 m_counter : 30;
uint32 m_active : 1;
uint32 m_endOfList : 1;
void* m_entry;
};[/code]

Share this post


Link to post
Share on other sites
[quote name='Adam_42' timestamp='1318802176' post='4873226']
Also note that you can have more than 32-bits worth of values in a bitfield ...

[/quote]

Of course, i should have thought about it thanks alot. That should do it, only one bit is used by m_active and m_endOfList. By the way, what is the term used for this notation with the : at the end of member variables ?

Share this post


Link to post
Share on other sites
[quote name='Adam_42' timestamp='1318802176' post='4873226']
[code]struct HandleEntry
{
HandleEntry();
explicit HandleEntry(uint32 nextFreeIndex);

uint32 m_nextFreeIndex : 24;
uint32 m_counter : 30;
uint32 m_active : 1;
uint32 m_endOfList : 1;
void* m_entry;
};[/code]
[/quote]

Out of curiosity, the number and the colon in "[b]uint32 m_nextFreeIndex[/b] [color="#ff0000"][b]: 24[/b][/color];" is just pseudocode, right? It's not valid C++, is it? [img]http://public.gamedev.net/public/style_emoticons/default/huh.gif[/img]

Share this post


Link to post
Share on other sites
[quote name='Servant of the Lord' timestamp='1318804915' post='4873248']
Out of curiosity, the number and the colon in "[b]uint32 m_nextFreeIndex[/b] [color="#ff0000"][b]: 24[/b][/color];" is just pseudocode, right? It's not valid C++, is it? [img]http://public.gamedev.net/public/style_emoticons/default/huh.gif[/img]

[/quote]



Yes, it's totally valid C++ code. [img]http://public.gamedev.net/public/style_emoticons/default/smile.gif[/img] But i don't know the term used for it. The variable to the left of the : will use the number of bits on the right. So if you have four 32 bits contiguous integer variables , you can use x bits for the first, y for the second, z for the third and w for the fourth assuming x+y+z+w <= 64.

Share this post


Link to post
Share on other sites
[quote name='Adam_42' timestamp='1318802176' post='4873226']
[code]struct HandleEntry
{
HandleEntry();
explicit HandleEntry(uint32 nextFreeIndex);

uint32 m_nextFreeIndex : 24;
uint32 m_counter : 30;
uint32 m_active : 1;
uint32 m_endOfList : 1;
void* m_entry;
};[/code]
[/quote]With a definition like that, I would make m_nextFreeIndex perhaps just a regular variable. 24+30+1+1 = 56 but it'll be padded up to 64 bits anyway (excluding the void pointer for the moment), with an unused 8 bits somewhere. As such, removing the ": 24" means that it wont have to do any masking to access that variable, under the hood.
Or if counter is used more then perhaps swap the order of those and remove the ": 30" instead.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this