From: Andrew Tridgell Date: Sat, 29 Jul 2000 04:52:05 +0000 (+0000) Subject: optimisations from Rich Salz X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/3d38277706a5155d57563d1221e7233d8159470a optimisations from Rich Salz --- diff --git a/backup.c b/backup.c index 52590c13..88f9eaed 100644 --- a/backup.c +++ b/backup.c @@ -197,7 +197,7 @@ static int keep_backup(char *fname) if (do_stat (fname, &st)) return 1; #endif - file = make_file (0, fname); + file = make_file (0, fname, 0); /* make a complete pathname for backup file */ if (strlen(backup_dir) + strlen(fname) > (MAXPATHLEN - 1)) { diff --git a/flist.c b/flist.c index f12bf893..e102076e 100644 --- a/flist.c +++ b/flist.c @@ -51,8 +51,60 @@ static char topsrcname[MAXPATHLEN]; static struct exclude_struct **local_exclude_list; +static struct file_struct null_file; + static void clean_flist(struct file_list *flist, int strip_root); +struct string_area *string_area_new(int size) +{ + struct string_area *a; + + if (size <= 0) size = ARENA_SIZE; + a = malloc(sizeof(*a)); + if (!a) out_of_memory("string_area_new"); + a->current = a->base = malloc(size); + if (!a->current) out_of_memory("string_area_new buffer"); + a->end = a->base + size; + a->next = 0; + + return a; +} + +void string_area_free(struct string_area *a) +{ + struct string_area *next; + + for ( ; a ; a = next) { + next = a->next; + free(a->base); + } +} + +char *string_area_malloc(struct string_area **ap, int size) +{ + char *p; + struct string_area *a; + + /* does the request fit into the current space? */ + a = *ap; + if (a->current + size >= a->end) { + /* no; get space, move new string_area to front of the list */ + a = string_area_new(size > ARENA_SIZE ? size : ARENA_SIZE); + a->next = *ap; + *ap = a; + } + + /* have space; do the "allocation." */ + p = a->current; + a->current += size; + return p; +} + +char *string_area_strdup(struct string_area **ap, const char *src) +{ + char* dest = string_area_malloc(ap, strlen(src) + 1); + return strcpy(dest, src); +} static void list_file_entry(struct file_struct *f) { @@ -413,8 +465,11 @@ static int skip_filesystem(char *fname, STRUCT_STAT *st) return (st2.st_dev != filesystem_dev); } +#define STRDUP(ap, p) (ap ? string_area_strdup(ap, p) : strdup(p)) +#define MALLOC(ap, i) (ap ? string_area_malloc(ap, i) : malloc(i)) + /* create a file_struct for a named file */ -struct file_struct *make_file(int f, char *fname) +struct file_struct *make_file(int f, char *fname, struct string_area **ap) { struct file_struct *file; STRUCT_STAT st; @@ -468,14 +523,14 @@ struct file_struct *make_file(int f, char *fname) if (lastdir && strcmp(fname, lastdir)==0) { file->dirname = lastdir; } else { - file->dirname = strdup(fname); + file->dirname = STRDUP(ap, fname); lastdir = file->dirname; } - file->basename = strdup(p+1); + file->basename = STRDUP(ap, p+1); *p = '/'; } else { file->dirname = NULL; - file->basename = strdup(fname); + file->basename = STRDUP(ap, fname); } file->modtime = st.st_mtime; @@ -491,12 +546,12 @@ struct file_struct *make_file(int f, char *fname) #if SUPPORT_LINKS if (S_ISLNK(st.st_mode)) { - file->link = strdup(linkbuf); + file->link = STRDUP(ap, linkbuf); } #endif if (always_checksum) { - file->sum = (char *)malloc(MD4_SUM_LENGTH); + file->sum = (char *)MALLOC(ap, MD4_SUM_LENGTH); if (!file->sum) out_of_memory("md4 sum"); /* drat. we have to provide a null checksum for non-regular files in order to be compatible with earlier versions @@ -513,7 +568,7 @@ struct file_struct *make_file(int f, char *fname) if (lastdir && strcmp(lastdir, flist_dir)==0) { file->basedir = lastdir; } else { - file->basedir = strdup(flist_dir); + file->basedir = STRDUP(ap, flist_dir); lastdir = file->basedir; } } else { @@ -533,7 +588,7 @@ void send_file_name(int f,struct file_list *flist,char *fname, { struct file_struct *file; - file = make_file(f,fname); + file = make_file(f,fname, &flist->string_area); if (!file) return; @@ -623,7 +678,6 @@ static void send_directory(int f,struct file_list *flist,char *dir) } - struct file_list *send_file_list(int f,int argc,char *argv[]) { int i,l; @@ -640,14 +694,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) start_write = stats.total_written; - flist = (struct file_list *)malloc(sizeof(flist[0])); - if (!flist) out_of_memory("send_file_list"); - - flist->count=0; - flist->malloced = 1000; - flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])* - flist->malloced); - if (!flist->files) out_of_memory("send_file_list"); + flist = flist_new(); if (f != -1) { io_start_buffering(f); @@ -935,10 +982,32 @@ void free_file(struct file_struct *file) if (file->basename) free(file->basename); if (file->link) free(file->link); if (file->sum) free(file->sum); - memset((char *)file, 0, sizeof(*file)); + *file = null_file; } +/* + * allocate a new file list + */ +struct file_list *flist_new() +{ + struct file_list *flist; + + flist = (struct file_list *)malloc(sizeof(flist[0])); + if (!flist) out_of_memory("send_file_list"); + + flist->count=0; + flist->malloced = 1000; + flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])* + flist->malloced); + if (!flist->files) out_of_memory("send_file_list"); +#if ARENA_SIZE > 0 + flist->string_area = string_area_new(0); +#else + flist->string_area = 0; +#endif + return flist; +} /* * free up all elements in a flist */ @@ -946,11 +1015,14 @@ void flist_free(struct file_list *flist) { int i; for (i=1;icount;i++) { - free_file(flist->files[i]); + if (!flist->string_area) + free_file(flist->files[i]); free(flist->files[i]); } memset((char *)flist->files, 0, sizeof(flist->files[0])*flist->count); free(flist->files); + if (flist->string_area) + string_area_free(flist->string_area); memset((char *)flist, 0, sizeof(*flist)); free(flist); } @@ -979,7 +1051,13 @@ static void clean_flist(struct file_list *flist, int strip_root) if (verbose > 1 && !am_server) rprintf(FINFO,"removing duplicate name %s from file list %d\n", f_name(flist->files[i-1]),i-1); - free_file(flist->files[i]); + /* it's not great that the flist knows the semantics of the + * file memory usage, but i'd rather not add a flag byte + * to that struct. XXX can i use a bit in the flags field? */ + if (flist->string_area) + flist->files[i][0] = null_file; + else + free_file(flist->files[i]); } } diff --git a/main.c b/main.c index 6a4d1031..b402c7ad 100644 --- a/main.c +++ b/main.c @@ -271,6 +271,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) } send_files(flist,f_out,f_in); + io_flush(); report(f_out); io_flush(); exit_cleanup(0); @@ -323,6 +324,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) set_error_fd(error_pipe[1]); recv_files(f_in,flist,local_name,recv_pipe[1]); + io_flush(); report(f_in); write_int(recv_pipe[1],1); @@ -475,11 +477,11 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[]) io_flush(); wait_process(pid, &status); } - report(-1); if (remote_version >= 24) { /* final goodbye message */ read_int(f_in); } + report(-1); exit_cleanup(status); } diff --git a/rsync.h b/rsync.h index f9f0fd4f..0742d431 100644 --- a/rsync.h +++ b/rsync.h @@ -305,10 +305,20 @@ struct file_struct { }; +#define ARENA_SIZE (32 * 1024) + +struct string_area { + char *base; + char *end; + char *current; + struct string_area *next; +}; + struct file_list { int count; int malloced; struct file_struct **files; + struct string_area *string_area; }; struct sum_buf {