/* 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;
}