Knowing new[]'s overhead in a compiler-independent way

Programming, for all ages and all languages.
Post Reply
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Knowing new[]'s overhead in a compiler-independent way

Post by Neolander »

In C++, the array version of new allocates some extra storage space alongside the allocated object, so that it may store the array's size in order to call each element's destructor later.

My question is : is there a clean, compiler-agnostic way to know about the size of the actually allocated object (overhead included) without actually performing the allocation ?

The only option which I currently see is to create a special version of operator new[] for that purpose, which takes a size_t reference as a parameter, stores the result in it, and always returns NULL. Not exactly what I'd call clean, as it creates some very confusing syntax. ("Wait a minute, why does he use placement new here to do... err... what ?")

Any better idea ?
Last edited by Neolander on Tue Jul 05, 2011 10:26 am, edited 1 time in total.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Knowing new[]'s overhead in a compiler-independent way

Post by bluemoon »

But why would you try to optimize new, and introduce a special new that may break with other code?
And I seriously doubt that extra tidy size, along with other possible header and footer, make a sensible different in terms of memory footprint for array of elements,
and the related processing time is neglectable compare with the actual memory allocation.
My question is : is there a clean, compiler-agnostic way to know about the size of the actually allocated object (overhead included) without actually performing the allocation ?
memory allocation routines (new) are defined in the stdc++ library, and can be replaced.
it is meant to be isolated from compiler, so your question on "compiler-agnostic" way, well, the whole business is compiler-agnostic.
To determinate the size, check the library source code.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Owen »

...the size-of-array header is added by the compiler, not the library.

Also, be aware: if your operator new returns NULL, std::bad_alloc will be thrown.
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Neolander »

@Owen : Nope, because I have followed berkus' advice of putting a throw() somewhere in my allocator declarations :) User-space new and delete will probably be standards-compliant and have full exception support, but at kernel level I want neither exceptions nor the hurdle of playing with nothrow objects all the time, so standards be damned...

@bluemoon : As Owen says, the situation is not this simple. When you write...

Code: Select all

Foo* bar = new Foo[5]();
delete[] bar;
...four things happen :
  1. Memory for the array is allocated
  2. Each Foo in the array is initialized
  3. Each Foo in the array is destroyed
  4. Memory for the array is freed
The funny part is, library implementations only take care of 1 and 4. 2 and 3 are the job of the compiler. A corollary of this is that libraries may only implement the memory allocator part of new[] (operator new[]), which is basically a shortcut for malloc : you get asked to allocate x bytes of data, without knowing which part will be used to store the compiler's management structures, and which part actually contains the array.

So before operator new[] is called, there is no obvious way to know how much memory will actually have to be allocated by it. And for what I want to do (avoiding multiple allocations by allocating one big buffer and slicing it in bits), this is a problem. Hence my question : is there a clean way to know, without performing any allocation, how much memory a new[] will eat up ? A way that does not involve dirty hacks like an overloaded new[] that looks like a placement new and doesn't actually allocate memory...
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Solar »

...and the compiler will slice it in whatever way applicable.

I think you're on a wild goose chase here.
Every good solution is obvious once you've found it.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by JamesM »

Code: Select all

static bool initializing = false;
static size_t overhead = 0;
void *operator new[](size_t sz) {
    if (initializing) {
        overhead = sz;
        return (void*)~0UL;
    } else {
        // Do normal memory allocation
    }
}

void init() {
    initializing = true;
    volatile void *x = new int[0];
    initializing  = false;
}
?
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Neolander »

JamesM wrote:

Code: Select all

static bool initializing = false;
static size_t overhead = 0;
void *operator new[](size_t sz) {
    if (initializing) {
        overhead = sz;
        return (void*)~0UL;
    } else {
        // Do normal memory allocation
    }
}

void init() {
    initializing = true;
    volatile void *x = new int[0];
    initializing  = false;
}
?
I think this is the option I'd end up choosing, save for some tweaking. Still a bit ugly, but better than my idea.
Last edited by Neolander on Wed Jul 06, 2011 4:31 am, edited 1 time in total.
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Neolander »

berkus wrote:I honestly don't follow what's the problem. Your operator new[] implementation will be called with exactly how many bytes are needed, including the overhead.
I want to know how much memory is needed by a new[] before actually allocating the memory :) The idea is that in a scenario where I'd have to allocate lots of related small heap objects that will also be freed at the same time (strings, typically), I can (and need to) get much better performance by calculating the amount of required memory and allocating everything at once.
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Ready4Dis »

Last time I played around overloading new for some memory management/tracking software, if I did a new char[10], it would ask my new for exactly 10 bytes. (When I say overloaded, I don't mean a single overload for a class, just overloaded generic new/delete). As far as I know, new doesn't have much overhead over than what is used by whatever malloc implementation it calls, which is obviously dependant on your particular malloc. I could be wrong (wouldn't be the first time), but unless you use something with GC (garbage collection) new shouldn't need any extra space. If you're writing an OS, you are probably going to have to use your own NEW implementation anyways, so it's up to you what overhead it has. If you are using a cross compiled GCC, look at the sources to see if it doesn't anything special for new. I'm not really sure what overhead you are talking about or looking to avoid (overhead as in cpu cycles, or in memory footprint).
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Owen »

..try "new SomeTypeWithADestructor[10]"
User avatar
blobmiester
Member
Member
Posts: 45
Joined: Fri Jul 16, 2010 9:49 am

Re: Knowing new[]'s overhead in a compiler-independent way

Post by blobmiester »

Owen wrote:..try "new SomeTypeWithADestructor[10]"
Which will translate into (theoretically equivalent) (SomeTypeWithADestructor*)malloc(sizeof (SomeTypeWithADestructor) * 10).

The destructor/constructor calling is handled by the compiler at new/delete for the type.

As for new[]'s overhead. The compiler doesn't decide what it is. The implementation of operator new() does. There is no possible way to detect this or control it -- unless you write your own malloc/new implementation (which isn't that hard if you are caring this much about allocation speed).

On second thought, you could just malloc() a pool of memory and use placement new/delete to allocate (which is what the STL does). That is what I'd do.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Owen »

blobmiester wrote:
Owen wrote:..try "new SomeTypeWithADestructor[10]"
Which will translate into (theoretically equivalent) (SomeTypeWithADestructor*)malloc(sizeof (SomeTypeWithADestructor) * 10).
If it translates into that, how does delete [] thatBuffer know how many destructors it needs to run? Conclusion: It doesn't translate into that.

It translates into ::operator new[](some value > sizeof (T) * 10).

To start writing things in pseudo-C++0X, the compiler-side logic for new probably looks something like the following:

Code: Select all

T* buf;
if(alignof(T) > alignof(size_t)) {
    buf = ::operator new(sizeof(T) * (nElements + 1));
    size_t* count = (size_t*) &buf[0];
    *count = nElements;
    buf += 1;
} else {
    size_t* count = ::operator new(sizeof(T) * nElements + sizeof(size_t));
    buf = (T*) count[1];
    *count = nElements;
}
for(size_t i = 0; i < nElements; i++) buf[i]->T();
return buf
The destructor/constructor calling is handled by the compiler at new/delete for the type.
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Knowing new[]'s overhead in a compiler-independent way

Post by Neolander »

And this is exactly what I got in practice ! Good to know that new[] avoids wasting space on types without a destructor though :)

(Ah, a deep breath of 'net after some internet-less holidays)
Post Reply