2010-03-17 16 views
5

Acabo de empezar con C y tengo muy pocos conocimientos sobre problemas de rendimiento con malloc() y free(). Mi pregunta es la siguiente: si tuviera que llamar al malloc() seguido de dentro de un bucle while que bucles para, digamos, 20 iteraciones, ¿funcionaría más lento en comparación con llamar a free()fuera del el bucle?C Programación: malloc y libre dentro de un bucle

De hecho, estoy usando el primer método para asignar memoria a un búfer, leer una cadena de longitud variable desde un archivo, realizar algunas operaciones de cadena y luego borrar el búfer después de cada iteración. Si mi método resulta en una gran cantidad de gastos generales, me gustaría pedir una mejor manera de lograr los mismos resultados.

+5

No se puede llamar libre fuera del bucle si hace una llamada a malloc en su interior, o tendrá que filtrarse la memoria para todos pero el malloc desde la última iteración. Sin embargo, puede usar realloc en lugar de malloc, y luego libre. – Cascabel

+0

@Jefromi: Creo que deberías hacer un comentario. –

+2

Tu inglés está bien, es mejor que el inglés de los novatos en SO. –

Respuesta

13

Definitivamente más lento. (Pero recuerde que necesita para equilibrar el número de malloc y free de otro modo se obtiene una pérdida de memoria.)

Si la longitud varía, puede utilizar realloc para ampliar el tamaño del búfer.

void* v = malloc(1024); 
size_t bufsize = 1024; 

while(cond) { 
    size_t reqbufsize = get_length(); 
    if (reqbufsize > bufsize) { 
     bufsize = reqbufsize * 2; 
     v = realloc(v, bufsize); 
    } 
    // you may shrink it also. 

    do_something_with_buffer(v); 
} 

free(v); 
+2

+1 - pero ¿no crees que 'bufsize = reqbufsize * 2;' es un poco drástico? : P –

+0

Quizás. La implementación de MSVC2k8 de 'std :: vector' aumenta su buffer en un 150% cuando se reasigna. –

+4

@BillyONeal: Esa es en realidad una forma bastante común de hacer las cosas. – Dinah

3

Si conoce la longitud máxima del búfer, o puede establecer un máximo razonable, podría usar el mismo búfer para cada iteración. De lo contrario, lo que estás haciendo debería estar bien.

0

Depende de la implementación de malloc y gratis.

La mejor manera de responder a su pregunta es la construcción de un punto de referencia ...

1

Depende de lo que necesite para el búfer.

¿Realmente necesita borrarlo después de cada iteración o quizás un \0 char al final sería suficiente para marcar el final de una cadena? Después de todo, eso es lo que utilizan las diversas llamadas a la biblioteca str.

Si realmente necesita borrarlo puede usar bzero(). Ciertamente, malloc'ing y free'ing en cada iteración es un desperdicio de recursos, ya que puede reutilizar felizmente el buffer.

Se produciría un problema diferente si tuviera que paralelizar el bucle for, es decir, tener varios subprocesos simultáneos usándolo.

Ejemplo simple, de la vida real: usando una cubeta para transportar agua. Supongamos que necesita hacer varios viajes con ese cubo: ¿tendría sentido recogerlo, usarlo, dejarlo, recogerlo de nuevo, usarlo, etc.? Puede volver a usar el cucharón tantas veces como sea posible. Si, por otro lado, el cubo necesita ser utilizado por usted y más personas, ya sea que organice el acceso al cucharón o necesite más cubetas.

Última sugerencia: no se preocupe por las actuaciones ahora. Dicen que la optimización temprana es la raíz de todo mal, y pronto entenderán por qué.

En primer lugar, comprenda el problema: escriba el código que puede desecharse. Experimentar. En segundo lugar, pruébelo. Asegúrate de que hace lo que necesitas. En tercer lugar, optimizarlo. Haga que el ciclo se ejecute diez mil veces y mida cuánto tiempo lleva. A continuación, mueva el malloc hacia afuera y vuelva a medir (use el comando de shell time si está bajo UNIX). En cuarto lugar, reescríbalo porque su primer experimento probablemente será un desastre de parches de try-retry-not working code.

Enjuague, repita.

pd: diviértanse mientras tanto. Se supone que es interesante, no frustrante.

1

En general, todo lo que se puede mover fuera de un bucle debería ser. ¿Por qué repetir la misma acción cuando puedes hacerlo una sola vez?

Justin Ethier tiene razón, asigne un búfer que se ajuste cómodamente al hilo más grande y reutilícelo.

6

Para 20 iteraciones, no debe preocuparse por el rendimiento de malloc/free.

Incluso para mucho más (un par de órdenes de magnitud), no debe comenzar a pensar en optimizaciones hasta que no describa el código y comprenda qué es lento.

Finalmente, si va a liberar el búfer, no es necesario borrarlo primero. Incluso si tuviera que mover el malloc/free fuera del bucle (utilizando un búfer máximo como lo sugiere Justin), no debería necesitar borrar explícitamente el búfer.

6

No se puede llamar libre fuera del bucle si llama dentro malloc:

char * buffer; 
for (int i = 0; i < num_files; i++) { 
    buffer = malloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 

Habrás malloc'ed num_files veces, pero sólo una vez liberado - se filtró la memoria de todos excepto el último !

Hay dos opciones principales - malloc antes del bucle (o simplemente utilizar una matriz) si sabe un tamaño que funcione para todo, o utilizar realloc:

char * buffer = NULL; 
for (int i = 0; i < num_files; i++) { 
    buffer = realloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 
0

Proceso mejor. Toma un poco de pseudo código:

#define BLOCK_SIZE 1024 // or about the bigger size of your strings. 

char *buffer = (char *) malloc(BLOCK_SIZE) 

for(int i=0; i<20; i++) 
{ 
    while (more bytes left to read) 
    { 
    read full string or BLOCK_SIZE bytes at max // most calls work this way 
    proces bytes in buffer 
    } 
} 

free(buffer); 
Cuestiones relacionadas