Jump to content
  • Advertisement
Sign in to follow this  
scarypajamas

.data segment vs malloc/new

This topic is 625 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Lets say an application knows how much memory it needs and wants to allocate it all up front and then manage it itself.  Is there a disadvantage to using the .data segment to instruct the OS to reserve the space when it loads the process?  I'm asking this from the perspective that you'd alternatively just request the memory at runtime with one call to malloc.

// In this example, the OS reserves 1 gigabyte for the process because the .data segment needs 1 gigabyte of space.
// If I know my process only needs a gigabyte, then why not reserve it through the .data segment as shown here?
// What is the advantage of dynamically allocating the memory with malloc?
// My question assumes malloc would just be called once at startup to get the gigabyte.

char memory_needed_for_app[1024 * 1024 * 1024];

int main(int argc, char *argv[])
{
    return 0;
}
Edited by scarypajamas

Share this post


Link to post
Share on other sites
Advertisement
Most compilers have the option to increase stack space, although I was unable to find it after a quick glance of Visual Studio's settings. Unless you explicitly tell the compiler to change the amount of stack space and unless the OS honors the request, the code you wrote will either not compile or will crash hard. Even if it worked, you'd be left with a GB of characters, not a GB of free space. Sure, you could access that space for other uses through clever pointer tricks, but God help you during debugging!

Why do you want to do this? If you need that much space, the heap is much better suited for this purpose.

[edit]

It sounds like you want to make your own memory manager. That can be done, and often is, but never via the stack. Truthfully, with smart pointers and containers, the reasons for creating a memory manager are getting fewer and fewer. If this is what you're after, you should Google some examples. It is a non-trivial task. Edited by MarkS

Share this post


Link to post
Share on other sites
Thank you for the reply.
 

Most compilers have the option to increase heap space, although I was unable to find it after a quick glance of Visual Studio's settings. Unless you explicitly tell the compiler to change the amount of heap space and unless the OS honors the request, the code you wrote will either not compile or will crash hard

Would making one call to malloc for a gigabyte avoid heap space issues? FWIW Visual Studio 2015 didn't have an issue running my example.
 

Even if it worked, you'd be left with a GB of characters, not a GB of free space. Sure, you could access that space for other uses through clever pointer tricks, but God help you during debugging!

The intent is its a byte not a character, perhaps using int8_t would make that more clear.
 

It sounds like you want to make your own memory manager. That can be done, and often is, but never via the heap.

How would you do it without the heap?
 

Truthfully, with smart pointers and containers, the reasons for creating a memory manager are getting fewer and fewer. If this is what you're after, you should Google some examples. It is a non-trivial task.

My application (mostly) just needs frame allocators (AKA pointer bump allocators). The overall architecture, using a frame allocator, is simple:

1. Load resources that will always exist in memory at app start.
-> Remember the byte offset within the allocator at this point.
2. Load a level and all the resources that are needed for it.
3. When the level unloads, then restore the allocator back to the byte offset saved earlier and continue from step #2.

I'm more or less wondering if the .data segment is any different from the applications heap space. As in, is it less optimized, constantly paging, is this not portable, etc...? Obviously, if your not sure how much space you'll need until runtime, then you need to use malloc and friends. But in my case, I know how much space I need. Edited by scarypajamas

Share this post


Link to post
Share on other sites

When you are realy willing to write some level space management over a memory management system you should definetly go for malloc/free here. I have implemented an allocator subsystem that initially uses

byte* MemoryBlock[RESERVED_STATIC_DATA_MEMORY];

void* Pointer() { return ((void*)MemoryBlock); }
size_t BlockSize() { return sizeof(MemoryBlock); }

inside a cpp file as its internal base memory to preset the initial allocator and use for some game/engine internal memory allocation. It is set via my config file to 64 byte all at all (where byte here is unsigned char). Then I have a class HeapAllocator that is created inside the reserved static memory block and well works on the heap.

 

The original reason why one should use some kind of memory management especially in games is that new/malloc and delete/free will fragment the heap because of the following scenario

allocate 4 byte
{ 0 0 0 0 }
allocate 2 byte
{ 0 0 0 0 0 0 }
allocate 6 byte
{ 0 0 0 0 0 0 0 0 0 0 0 0 }
release 2 byte
{ 0 0 0 0 X X 0 0 0 0 0 0 }
allocate 3 byte
{ 0 0 0 0 X X 0 0 0 0 0 0 0 0 0 }
release 4 byte
{ X X X X X X 0 0 0 0 0 0 0 0 0 }
allocate 5 byte
{ 0 0 0 0 0 X 0 0 0 0 0 0 0 0 0 }
allocate 3 byte
{ 0 0 0 0 0 X 0 0 0 0 0 0 0 0 0 0 0 0 }
allocate 3 byte
{ 0 0 0 0 0 X 0 0 0 0 0 0 0 0 0 0 0 0 }

As you see here your heap got fragmented because the last two 3 byte allocs would have fit into the 6 byte release but the 5 byte alloc came first so occupied this section in memory. To avoid this you might allocate over your heap allocator some ranges of data for your object manager with different sizes. The so called buckets have certain size and are used when you create objects (like when loading a level) depending on the objects size. When a bucket is running out of memory allocate a new block on the heap and chain it to that bucket.

 

This practice has some advantages because you allocate different sized ranges in different buckets and there will be less fragmenting when allocating releasing those objects.

 

To answer your last question, the .data segment depends on what it is initialized to and if it is static/const or variable. It is stored inside the assembly initially but I might be wrong, allocated on the heap when assembly loads as long as it is not static or const. It is higly OS dependent so dont trust the Klingon

Share this post


Link to post
Share on other sites

It is higly OS dependent so dont trust the Klingon


Maybe this is the answer then.

Right now I'm able to reserve 1 gigabyte in the data segment in MSVC 2015 (without modifying compiler options). It sparked my curiosity about the potential for using the data segment over malloc/free assuming your going to pool the memory yourself anyway. I suppose if its size is OS dependent, then that makes sense why you'd use malloc/free instead.

I've been able to find lots of information on process layout, but nothing with specifics on the data segment vs heap. I welcome more responses if anyone else knows anything about the subject.

Share this post


Link to post
Share on other sites

Right now I'm able to reserve 1 gigabyte in the data segment in MSVC 2015 (without modifying compiler options).


This must be a relatively new thing. I haven't tried this in years, but there was a time where stack space had to be preallocated and going beyond the stack caused a crash. My information may be out of date. A dynamic stack really doesn't make much sense though as that is basically what the heap is or was. Maybe the line is being blurred?

Share this post


Link to post
Share on other sites

I don't think it makes much of a difference from a performance perspective if your memory pool is global or on the heap. From an operating system perspective, both are just memory requested by the application, the only difference being when. Therefore I would use the heap because it allows you to have a more modular and reusable design. You also get the capability to ask for memory in blocks, so that your memory pool is aligned with the os page size on both ends, but this shouldn't matter very much, especially if your application isn't expected to page fault.

Share this post


Link to post
Share on other sites

 

Right now I'm able to reserve 1 gigabyte in the data segment in MSVC 2015 (without modifying compiler options).


This must be a relatively new thing. I haven't tried this in years, but there was a time where stack space had to be preallocated and going beyond the stack caused a crash. My information may be out of date. A dynamic stack really doesn't make much sense though as that is basically what the heap is or was. Maybe the line is being blurred?

 

 

Global variables are not on the stack. This means that they can indeed be arbitrarily large without compromising stack space. It's allocated in the ,data segment, not the stack.

 

However, the line is indeed blurred with respect to dynamic stacks. Compilers support segmented stacks, which are just that. This is often turned off by default, because it does have add performance cost to pushing and popping things from the stack.

Share this post


Link to post
Share on other sites

 

Right now I'm able to reserve 1 gigabyte in the data segment in MSVC 2015 (without modifying compiler options).


This must be a relatively new thing. I haven't tried this in years, but there was a time where stack space had to be preallocated and going beyond the stack caused a crash. My information may be out of date. A dynamic stack really doesn't make much sense though as that is basically what the heap is or was. Maybe the line is being blurred?

 

 

 

Don't confuse the data segment with the stack.

Globals are not allocated on the stack, so stack limitations shouldn't matter for their size.

There is likely OS differences in how much memory can be allocated for the data segment too though, but I'd expect the limit to be pretty large for modern OS:es.

 

I can't say I know, but my gut feeling is that the difference between defining a global variable with the space, or do one call to malloc at startup is minimal though. Possibly malloc is a tiny bit slower to allocate, but as soon as it's allocated, the difference should be nonexistant, memory is just memory after all.

 

If your memory management is better or worse then what malloc provides would highly depend on how you choose to implement it, and what your expected usage is...

 

Edit: Ninjad by the King :P

Edited by Olof Hedman

Share this post


Link to post
Share on other sites
I think the above code snippet might go into .bss, not into .data (since the array is not initialized, there's no reason it should be in .bss).

That being said, regarding "is there a disadvantage to using the .data segment", well yes of course there is. The executable's size grows by one gigybyte, and the (zero) data has to be read in from disk rather than using zero pages, around 250,000 hard faults.

Calling malloc once or even a few times is not only permissible and preferrable (due to better behavior), but the overhead is basically zero. It's freeing memory which tends to be more expensive, and with such huge blocks of data, faulting the pages is what dominates the overall cost (that's distributed over the application's lifetime, so not trivially measurable). The cost of one (or a dozen) calls to malloc is ridiculously small. You surely don't want to do a hundred allocations every frame, but here you will not notice them in any way.

Now, assuming the variable goes into .bss, is there a disadvantage in this? Only insofar as you don't control the initialization and insofar as it's unflexible and not error-tolerant. If it fails, the program instantly terminates with a user-incomprehensible error message. No fallback, no mitigation, no knowing what's wrong.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!