3

According to the answer to this question:

Difference between malloc and calloc?

Isak Savo explains that:

calloc does indeed touch the memory (it writes zeroes on it) and thus you'll be sure the OS is backing the allocation with actual RAM (or swap). This is also why it is slower than malloc (not only does it have to zero it, the OS must also find a suitable memory area by possibly swapping out other processes)

So, I decided to try it myself:

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

#define ONE_MB = 1048576

int main() {
    int *p = calloc(ONE_MB, sizeof(int));

    int n;
    for(n = 0; n != EOF; n = getchar()) ; /* Gives me time to inspect the process */

    free(p);
    return 0;
}

After executing this application, Windows's Task Manager would tell me that only 352 KB were being used out of RAM.

calloc memory allocation

It appears that the 1MB block I allocated is not being backed with RAM by the OS.


On the other hand, however, if I would call malloc and initialize the array manually:

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

#define ONE_MB = 1048576

int main() {
    int *p = malloc(sizeof(int) * ONE_MB);

    int n;

    /* Manual Initialization */
    for(n = 0; n < ONE_MB; n++)
        memory[n] = n;

    for(n = 0; n != EOF; n = getchar()) ; /* Gives me time to inspect the process */

    free(p);
    return 0;
}

Task Manager would show me that there is actually 4.452KB of RAM being used by the application.

malloc and manual init memory allocation


Was Isak incorrect about his argument? If so, what does calloc do then? Doesn't it zero the whole memory block, and therefore "touches" it, just as I did?

If that's the case, why isn't RAM being used in the first sample?

Community
  • 1
  • 1
Matias Cicero
  • 25,439
  • 13
  • 82
  • 154
  • `calloc()` does not use memory, it allocates it. See http://stackoverflow.com/questions/19991623/why-is-malloc-not-using-up-the-memory-on-my-computer/19991656#19991656 "calloc does indeed touch the memory " is not necessarily so. With page swapping all zero memory could be mapped to the same location, at least until the data written is interesting. – chux - Reinstate Monica Nov 18 '14 at 19:35
  • I believe your question is answered in the comments of the same post you linked to. – P.P Nov 18 '14 at 19:36
  • `If the allocated block consists mostly of new zero pages provided by the operating system, it can leave those untouched`. I'm allocating 1MB, what are the chances of all of them to be zero from the start? – Matias Cicero Nov 18 '14 at 19:38
  • 1
    Good answer here: http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc – indiv Nov 18 '14 at 19:40
  • 3
    @MatiCicero: If you get a fresh 1 MB of memory from the operating system, the chances of all bytes being zero are 100%. If you get 10000 GB of memory from the OS, the chances are still 100%. The only time your memory wouldn't be all zero (in the case of `malloc`) is once the memory allocator starts re-using freed memory from its own internal pool. – indiv Nov 18 '14 at 19:42
  • @MatiCicero The chances are pretty good. The NT kernel specifically maintains a collection of zeroed memory pages to satisfy allocations. – nobody Nov 18 '14 at 19:42
  • @indiv related question clarified enough for me. I understand your point now. It's good to learn something new! Thanks! – Matias Cicero Nov 18 '14 at 19:43
  • 1
    Advanced memory allocators can map the entire 1 MB allocation to a single page (say 512 byte) and zero that. Alternatively, since example 1 never uses the memory, code is fast and lean (memory consumption wise). No physical memory is used in example 1, it is only allocated. – chux - Reinstate Monica Nov 18 '14 at 19:51

1 Answers1

3

He was wrong in the point, that it is much slower because of it has to write 0 in the block first.

Any smart coded OS prepares such blocks for such purposes (where calloc() isn't the only case such blocks are used for) and if you call calloc() it just assigns such a block of zeroed memory to your process instead of a uninitialized one as it >could< do by calling malloc().

So it handles such blocks of memory the same way. and if the compiler/OS decides you don't ever/yet need the full 1MB it also dont' gives you a full 1MB block of the zeroed memory.

In How far he was right: If you heavily call calloc() and also use the memory, the OS could go out of zeroed memory which was probably prepared in some idle time.

This would be causing indeed the system to get a bit slower, as than the os is forced by a call to calloc() to write 0's in the block first.

But at all: There is no regulation about whether malloc/calloc have to allocate the memory on the call or just as you are using the memory. So your special example depends on the OS treatment.

dhein
  • 6,431
  • 4
  • 42
  • 74