Giter VIP home page Giter VIP logo

Comments (16)

seanmiddleditch avatar seanmiddleditch commented on May 16, 2024 2

Maybe the existing runtimes do by incident, I haven't checked, but you're relying on implementation detail of the runtimes.

Only some of them do that. Some of them do not. Especially when in debug builds with debug runtimes/libraries in play.

(or perhaps not bother overriding at all since they all use malloc underneath...)

This is not true. It may be true on some platforms (libstdc++ maybe) but is not true on others.

To be very clear, it is also not true to ever assume that one overload of new will ever call a different overload of new by default.

To do otherwise is to invoke undefined behavior.

If mimalloc is overriding new, I would not only absolutely expect it to override all overloads, I would also expect that with mimalloc's debug/security/correctness layer turned on that mimalloc would detect and raise an error when new and free (or malloc and delete) are inappropriately paired, just like some existing C++ standard library implementations do today.

from mimalloc.

Lastique avatar Lastique commented on May 16, 2024 1

The implementations call the non-throw versions and those are overridden.

I haven't found where, in mimalloc, they are overridden.

Even stronger, for overriding to work, you don't even need to override new as that eventually invokes malloc.

First, operator new doesn't necessarily have to call malloc. Maybe the existing runtimes do by incident, I haven't checked, but you're relying on implementation detail of the runtimes.

Second, if you want to rely on implementation details, then at least be consistent about it. Either override all operators, or none. At least, if the operators don't use malloc/free, they will be able to work with whatever heap they all use.

from mimalloc.

Lastique avatar Lastique commented on May 16, 2024 1

When the standard says throw bad_alloc then the operator should do it. It is the caller who should be able to do something about it, if he wants to. Also note that there is set_new_handler API.

from mimalloc.

daanx avatar daanx commented on May 16, 2024 1

Just pushed a new commit that implements the correct overriding for new/delete if compiling with a C++ compiler; adds overrides for all current new/delete variants including nothrow etc. When using a C compiler we cannot call get_new_handler or throw exceptions, so in that case these are not overridden at all and we rely on the standard implementations calling malloc/free under the hood. (we do override aligned_alloc as well so everything should work now) :-)

from mimalloc.

daanx avatar daanx commented on May 16, 2024

Hi, good suggestion. However, when I look at the standard, the default implementations refer to the throwing versions and those are overridden. So it seems to be ok to not override the nothrow_t versions explicitly right? I would like to reduce the override API as much as possible.

from mimalloc.

Lastique avatar Lastique commented on May 16, 2024

If you don't override all overloads provided by the compiler runtime then those overloads are linked to the program, which means some of the overloads will call mimalloc and others - compiler runtime. You need to override all memory allocation functions, including std::nothrow_t versions.

from mimalloc.

Lastique avatar Lastique commented on May 16, 2024

I'll add that the C++ standard is not really authoritative in this case as it doesn't deal with compiler implementations and ABI. And replacing memory allocations means dealing with both. You should be looking at C++ ABI documents and ABI libraries implementation to see which functions are actually called by the compiler. Plus the C/POSIX memory allocation functions.

from mimalloc.

daanx avatar daanx commented on May 16, 2024

@Lastique: If you don't override all overloads provided by the compiler runtime then those overloads are linked to the program, which means some of the overloads will call mimalloc and others - compiler runtime

I don't think that is the case. The implementations call the non-throw versions and those are overridden. Even stronger, for overriding to work, you don't even need to override new as that eventually invokes malloc. We override new anyways but that is just for better performance.
You are right though if the compiler library calls itself internal versions of malloc, but in that case we are in trouble anyway since any library function (like at_exit) might call the internal functions...

from mimalloc.

daanx avatar daanx commented on May 16, 2024

I see, it is a good argument. Also, I realized the current override of new is not according to the specification as we don't raise a bad_alloc exception on out-of-memory (but return NULL). Raising an exception in this case is not great though as there is nothing that can be done, calling exit or abort seems a better strategy. (worse, an most lazy commit systems new never fails but an access later on might which is arguably worse than returning NULL).

from mimalloc.

daanx avatar daanx commented on May 16, 2024

Well, of course :-) But I observed quite a speed improvement for redirecting new so there is quite a cost to supporting this behavior. The right thing to do seems to redirect to a mi_new function that calls the global new_handler if it cannot allocate -- this would preserve the standard semantics and still be efficient. And than also override the no_throw variants.

from mimalloc.

kickunderscore avatar kickunderscore commented on May 16, 2024

With the claim of a general usability of the library the decision for a standard-compliant behaviour should actually be easy. I am confident that mimalloc will nevertheless reach a top position in all performance comparisons.

from mimalloc.

daanx avatar daanx commented on May 16, 2024

Yes, I agree -- I will fix this soon. The best thing to do seems to override all and implementing the standard semantics. (or perhaps not bother overriding at all since they all use malloc underneath...)

from mimalloc.

kickunderscore avatar kickunderscore commented on May 16, 2024

or perhaps not bother overriding at all since they all use malloc underneath... πŸ‘

I also think you overestimate the importance of the operator new in modern C++ programs. Almost all dynamic memory allocations nowadays are made by standard container classes (like std::vector<>, std::list<> etc.) that use the std::allocator<> class, which conceptually separates the (possible bulk) memory allocation from the construction of (separate) instances via the placement new operator.

And no, this is not a request to overwrite std::allocator<>...

from mimalloc.

Lastique avatar Lastique commented on May 16, 2024

Most widespread standard libraries use operator new/operator delete in std::allocator. And I wouldn't underestimate the amount of allocations beside std::allocator. To give you a perspective, if you have std::vector<std::unique_ptr<T>> with N elements in your code, you have one to few allocations through std::allocator and N allocations directly via new.

I think, if mimalloc intends to replace the standard heap, operator new/operator delete should be overridden.

from mimalloc.

kickunderscore avatar kickunderscore commented on May 16, 2024

Most widespread standard libraries use operator new/operator delete in std::allocator.

Yeah, you're right. The std::allocator<> calls operator new and operator delete as functions directly. I wasn't aware of that.

However, I don't see much benefit in the overwriting as the original motivation of improved performance is hardly given anymore as soon as the operators implement the standard compliant behavior.

from mimalloc.

Lastique avatar Lastique commented on May 16, 2024

However, I don't see much benefit in the overwriting as the original motivation of improved performance is hardly given anymore as soon as the operators implement the standard compliant behavior.

I'm not sure I understand. If you mean operators are supposed to benefit from mimalloc overriding malloc and friends then that is not guaranteed by the standard.

from mimalloc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.