简体   繁体   中英

c++ realloc performance vs malloc

First of all, I know that I'm wrong but I don't know what is my mistake. According to this link , about "realloc" it says that

The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location. If the new size is larger, the value of the newly allocated portion is indeterminate.

So if we use "realloc" if it wants to allocate new location to data, it will copy previous data to new location. So if this is true I'm curios to know isn't that better to use free + malloc instead of realloc? Because I think copying previous data to new location would not be a good idea when we consider about performance.

Can any one help me to find out that where is my mistake? Thanks in advance.

Use realloc - It has a better idea of the structure of the heap and therefore will try to avoid doing the copy.

Doing the malloc/copy/free each time does not have this performance enhancement

The justification of realloc is that it's faster than "2nd malloc, manual copy, free". As you suspect, a normal free and malloc would be faster, but that's because they do less.

PS. In C++, realloc is very dangerous because it fails to call copy constructors. OTOH, std::vector::resize does call copy constructors, default constructors and/or destructors.

One thing to note is that multiple mallocs will be significantly faster than multiple reallocs.

As an example, assume that you wanted to grow memory by doubling each time. You could realloc a large chunk of memory. Another approach would be to make multiple malloc calls to create a vector of memory chunks.

Take the following example:

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

static const size_t INITIAL_MEMORY_SIZE = 2;
static const size_t NUM_ALLOCATIONS = 32;
static const size_t NUM_ITERATIONS = 100;

static void multiple_malloc() {
  size_t previous_size = 0;
  size_t current_size = INITIAL_MEMORY_SIZE;
  char* data[NUM_ALLOCATIONS];

  for (size_t i = 0; i < NUM_ALLOCATIONS; i++) {
    data[i] = malloc(sizeof(char) * current_size);
    assert(data[i]);
    current_size += previous_size;
    previous_size = current_size;
  }
  for (size_t i = 0; i < NUM_ALLOCATIONS; i++) {
    free(data[i]);
  }
}


static void multiple_realloc() {
  size_t current_size = INITIAL_MEMORY_SIZE;
  char* mem = 0;
  for (size_t i = 0; i < NUM_ALLOCATIONS; i++) {
    mem = (char*)realloc(mem, sizeof(char) * current_size);
    assert(mem);
    current_size += current_size;
  }
  free(mem);
}


static void run_test(
  const char* test_name,
  void allocate()) {
  clock_t start = clock();

  for (size_t i = 0; i < NUM_ITERATIONS; i++) {
    allocate();
  }

  clock_t end = clock();
  printf("%s: ran in %lf seconds.\n",
     test_name, (end - start) / (double)CLOCKS_PER_SEC);
}

int main(int argc, char** argv) {

  run_test("multiple_malloc", multiple_malloc);
  run_test("multiple_realloc", multiple_realloc);

  return 0;
}

The multiple mallocs will be significantly faster than the multiple reallocs:

$ ./misc_perf_test
multiple_malloc: ran in 0.171875 seconds.
multiple_realloc: ran in 7.859375 seconds.

When creating a data structure such as a map or list where you might want to pre-allocate a chunk of elements, malloc will be much faster.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM