/* bench_reflink.c — copiar un fichero: reflink (FICLONE), copy_file_range y read+write. * * Cierra el experimento 2 de SDD 25 seccion 9 (T11), que quedo sin medir porque exige mkfs sobre * un loop, o sea root. La pregunta: el "copiar en O(1)" que la gente espera de copy_file_range, * cuanto vale de verdad, y en que filesystem. * * Uso: bench_reflink (el dir debe estar en el FS que se quiere medir) * Se compila con: cc -O2 -o bench_reflink bench_reflink.c */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #define MB (1024*1024) static long SIZE = 64*MB; /* se puede fijar por argv[3] en MiB: la copia O(1) hay que verla PLANA */ #define ROUNDS 7 static inline double now_ns(void){ struct timespec t; clock_gettime(CLOCK_MONOTONIC,&t); return t.tv_sec*1e9+t.tv_nsec; } static int cmpd(const void*a,const void*b){ double x=*(const double*)a,y=*(const double*)b; return (x>y)-(x 1e6) printf("%-40s %9.3f ms %9.3f ms %8.0f MB/s\n",n,min/1e6,med/1e6,(double)SIZE/(min/1e9)/1e6); else printf("%-40s %9.3f ms %9.3f ms (plano: no mueve datos)\n",n,min/1e6,med/1e6); fflush(stdout); } static int src_fd(const char *dir,char *path,size_t n){ snprintf(path,n,"%s/origen.bin",dir); int fd=open(path,O_CREAT|O_RDWR|O_TRUNC,0644); if(fd<0) return -1; char *b=malloc(MB); memset(b,0xA5,MB); for(long i=0;i [MiB]\n",argv[0]); return 2; } const char *dir=argv[1], *etiqueta=argv[2]; if(argc>3) SIZE=atol(argv[3])*MB; char src[512],dst[512]; int in=src_fd(dir,src,sizeof src); if(in<0){ fprintf(stderr,"no pude crear el origen en %s: %s\n",dir,strerror(errno)); return 1; } snprintf(dst,sizeof dst,"%s/copia.bin",dir); printf("\n### copia de %ld MiB sobre %s\n",SIZE/MB,etiqueta); printf("%-40s %12s %12s\n","BENCH","min","mediana"); double r[ROUNDS]; int ok=0; /* 1. reflink de fichero entero: la copia O(1) de verdad (comparte extents COW). */ for(int q=0;q0) (void)!write(out,buf,n); } r[q]=now_ns()-t0; close(out); } report("read+write (1 MiB)",r,ROUNDS); free(buf); unlink(dst); unlink(src); close(in); return 0; }