3

When I allocate and free memory and afterwards I allocate memory that is max the size as the previously freed part.

May the 2nd allocation be faster than the first?

Maybe because it already knows a memory region that is free? Or because this part of the heap is still assigned to the process? Are there other possible advantages?

Or does it generally make no difference?

Edit: As asked in the comments:

  • I am especially interested in gcc and MSVC.
  • My assumption was that the memory was not "redeemed" by the OS before.

As there is a lot going about specific details about implementation, I'd like to make it more clear, that this is a hypothetical question. I don't intend to abuse this, but I just want to know IF this may occur and what the reasons for the hypothetical speedup might be.

Kami Kaze
  • 2,069
  • 15
  • 27
  • 5
    This is an implementation detail, so you'll need to specify a particular compiler - gcc, MSVC, or other. – sashoalm Jan 26 '17 at 08:48
  • And also there are a lot of `malloc` implementation such as `jemalloc` or `tcmalloc` – ymonad Jan 26 '17 at 08:51
  • @sashoalm Added the compilers I use frequently. But I thought this more of a theoretical question – Kami Kaze Jan 26 '17 at 08:52
  • I think this does even depends on the OS, since, despite there is usually a "redemption" time, a freed memory could be requested by any other application under certain conditions. – Carles Jan 26 '17 at 08:53
  • @ymonad never considered this, but yeah makes sense that there is not only 1 malloc... But It is more a question of theory than implementation. If some implementation use such techniques I would like to know. It is not that I want to abuse them specifically. – Kami Kaze Jan 26 '17 at 08:55
  • You probably don't need to worry about this. – Jabberwocky Jan 26 '17 at 08:56
  • @KamiKaze The problem is that it varies depending on the compiler and OS. So while it might be hypothetically true on MSVC under Windows, it might be the opposite on GCC under Linux. – sashoalm Jan 26 '17 at 08:57
  • @MichaelWalz Do you mean that the performance difference is generally negligible? – Kami Kaze Jan 26 '17 at 09:02
  • @KamiKaze: The point is that you can't know, and that you **should** not bother with second-guessing it. The user may have switched the system's `malloc()` implementation with something else entirely, for whatever reason. Debugging instrumentation, for example, at which point performance considerations become secondary. – DevSolar Jan 26 '17 at 09:36
  • @KamiKaze yes, exactly – Jabberwocky Jan 26 '17 at 09:59
  • @DevSolar I am aware that I should not optimize for such behavior as it is implementation defined. It is just a theoretical question that came to my mind. – Kami Kaze Jan 26 '17 at 10:20

3 Answers3

3

Memory allocation with malloc should be faster whenever you avoid making system calls like sbrk or mmap. You will at least save a context switch.

Make an experiment with the following program

#include <stdlib.h>

int main() {

    void* x = malloc(1024*1024);
    free(x);
    x = malloc(1024*1024);

}

and run it with command strace ./a.out

When you remove call to free you will notice two additional system calls brk.

Grzegorz Żur
  • 47,257
  • 14
  • 109
  • 105
  • The implied assumption that `malloc()` always uses `sbrk()` at all is faulty. The `malloc()` implementation may use `mmap()` instead, or whatever mechanics it deems appropriate. – DevSolar Jan 26 '17 at 09:31
  • @DevSolar Whichever system call is used, it is still an additional system call which can be avoided and this is the point. – Grzegorz Żur Jan 26 '17 at 09:41
  • ...except on systems where it does not make a difference... I dislike blanket statements like this. (Not my downvote though.) – DevSolar Jan 26 '17 at 09:43
  • 1
    The answer though is on target to my question(at least partially). I am aware (and I hope I made it clear) that there is no "this is always the case", but "this might happen with the right circumstances". – Kami Kaze Jan 26 '17 at 10:12
3

On some common platforms like GCC x86_64, there are two kinds of malloc(): the traditional kind for small allocations, and the mmap kind for large ones. Large, mmap-based allocations will have less interdependence. But traditional small ones will indeed experience a big speedup in some cases when memory has previously been free()'d.

This is because as you suggest, free() does not instantly return memory to the OS. Indeed it cannot do so in general, because the memory might be in the middle of the heap which is contiguous. So on lots of systems (but not all), malloc() will only be slow when it needs to ask the OS for more heap space.

Community
  • 1
  • 1
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
2

Here's simple banchmark I compiled at -O1:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv){
    for(int i=0;i<10000000;i++){
        char  volatile * p = malloc(100);
        if(!p) { perror(0); exit(1); }
        *p='x';
        //free((char*)p);
    }

    return 0;
}

An iteration cost about 60ns with free and about 150ns without on my Linux. Yes, mallocs after free can be significantly faster.

It depends on the allocated sizes. These small sizes will not be returned to the OS. For larger sizes that are powers of two, the glibc malloc starts mmaping and unmmapping and then I'd expect a slowdown in the freeing variant.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • I don't think this proves anything, since the actual allocation could be delayed to just before the point where you use that memory. Add `p[0] = i;` to your loop. – Lundin Jan 26 '17 at 09:26
  • @Lundin I first did just that with char volatile *p. Didn't make significant difference so I removed it. Readded it now. – Petr Skocik Jan 26 '17 at 09:30