malloc sizeof
¿Qué tan malo es seguir llamando a malloc() y free()? (7)
En su ejemplo, su función ya contiene un syscall, por lo que el costo relativo de malloc
/ free
será virtualmente inmensurable. En mi sistema, un "viaje redondo" de malloc
/ free
tiene un promedio de alrededor de 300 ciclos, y las llamadas más baratas (obtener la hora actual, pid, etc.) cuestan al menos 2500 ciclos. Espere que recv
costará fácilmente 10 veces más, en cuyo caso el costo de asignar / liberar memoria será como máximo aproximadamente el 1% del costo total de esta operación.
Por supuesto, los tiempos exactos variarán, pero los órdenes de magnitud aproximados deberían ser bastante invariantes en todos los sistemas. Ni siquiera empezaría a considerar la eliminación de malloc
/ free
como una optimización, excepto en las funciones que son puramente espacio de usuario. Donde probablemente sea más valioso ir sin una asignación dinámica es en operaciones que no deberían tener casos de fallas. Aquí el valor es que usted simplifique y fortalezca su código al no tener que preocuparse de qué hacer cuando falla malloc
.
Estoy enviando un archivo de texto: el cliente-servidor divide el texto en paquetes de 512 bytes, pero algunos paquetes contienen texto de tamaño inferior al máximo, así que en el lado de los servidores, al recibir cada paquete, estoy llamando a malloc () para construir una cadena nuevamente ¿Es esta una mala práctica? ¿Es mejor mantener un búfer de trabajo que pueda ajustarse a la longitud máxima y seguir iterando, copiando y sobrescribiendo sus valores?
ok @nm aquí está el código, esto si está dentro de un bucle for (;;) despertado por el select ()
if(nbytes==2) {
packet_size=unpack_short(short_buf);
printf("packet size is %d/n",packet_size);
receive_packet(i,packet_size,&buffer);
printf("packet=%s/n",buffer);
free(buffer);
}
//and here is receive_packet() function
int receive_packet(int fd,int p_len,char **string) {
*string = (char *)malloc(p_len-2); // 2 bytes for saving the length
char *i=*string;
int temp;
int total=0;
int remaining=p_len-2;
while(remaining>0) {
//printf("remaining=%d/n",remaining);
temp = recv(fd,*string,remaining,0);
total+=temp;
remaining=(p_len-2)-total;
(*string) += temp;
}
*string=i;
return 0;
}
Hay gastos generales asociados con llamar a malloc y gratis. Se debe asignar un bloque desde el montón y marcarlo como en uso, cuando se libera la revisión. Sin saber qué sistema operativo o complaciente está utilizando, esto podría estar en la biblioteca c o en el nivel de gestión de memoria del sistema operativo. Ya que estás haciendo un montón de mallocs y libres, podrías terminar fragmentando gravemente tu montón, donde es posible que no tengas suficiente memoria libre contigua para hacer un malloc en otro lugar. Si puede asignar solo un búfer y seguir reutilizándolo, generalmente será más rápido y tendrá menos peligro de fragmentación del montón.
He encontrado que malloc, realloc y free son bastante caros. Si puedes evitar malloc, es mejor reutilizar la memoria que ya tienes.
Editar:
Parece que estoy equivocado acerca de lo caro que es el malloc. Algunas pruebas de tiempo con la versión 2.14 de GNU C Library en Linux muestran que para una prueba que recorre 100.000 veces y asigna y libera 512 ranuras con tamaños aleatorios de 1 a 163840 bytes:
tsc average loop = 408
tsc of longest loop = 294350
Por lo tanto, perder 408 ciclos haciendo malloc
o new
en un bucle interno estrecho sería algo tonto. Aparte de eso no te preocupes por eso.
Llamar a malloc / free en realidad puede aumentar la memoria utilizada por su proceso (sin fugas involucradas), si el tamaño pasado a malloc es variable, como lo demuestra esta pregunta:
Uso de la memoria del programa C - más memoria reportada que asignada
Así que el enfoque de búfer único es probablemente el mejor.
Malloc es generalmente bastante barato. Solo es caro si genera un syscall para obtener más espacio de almacenamiento dinámico. Por ejemplo, en sistemas similares a UNIX, eventualmente generará una llamada sbrk que será costosa. Si repetidamente malloc y liberas el mismo tamaño de memoria, lo harás loco rápidamente. Por ejemplo, considere el siguiente pequeño programa de prueba:
#include <stdlib.h>
int main()
{
int i=0;
int *ptr;
for(int i=0; i<1e6; i++) {
ptr = malloc(1024*sizeof(int));
free(ptr);
}
}
Asigna 1024 enteros y los libera y lo hace un millón de veces. Al ejecutar esto en mi modesta y pequeña computadora Chromebook convertida en Linux, obtengo tiempos que se ven así:
time ./test
real 0m0.125s
user 0m0.122s
sys 0m0.003s
Ahora, si comento el malloc y la parte libre del bucle, obtengo estos tiempos:
time ./test
real 0m0.009s
user 0m0.005s
sys 0m0.005s
Entonces, ves que malloc y free tienen gastos generales, aunque creo que ser diez veces más caro que no hacer nada es terriblemente mucho más caro.
Es especialmente rápido si puede seguir reutilizando el mismo trozo de montón una y otra vez (como es el caso aquí). Por supuesto, si continuara asignando y haciendo crecer el programa repetidamente, llevaría más tiempo porque eso daría como resultado algunos eventos.
Por supuesto, su millaje puede variar según el sistema operativo, el compilador y la implementación de la plataforma.
Medir el rendimiento de las dos soluciones. Ya sea perfilando o midiendo el rendimiento. Es imposible decir algo con certeza.
Sólo las pruebas pueden decir. Sin embargo, cuando la programación en CI se equivoca al evitar malloc, ya que las fugas de memoria pueden ser bastante difíciles de solucionar si se crea una por accidente.