diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-03-05 18:13:41 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-03-05 18:13:41 +0300 |
commit | 4f764637e6603d8dee324031944772db05c11058 (patch) | |
tree | 52ff24339fda8a2964559520e506a193e70f08e5 /source/blender/blenloader | |
parent | 3a7b420ec66d2fa64814997f205f8d307fce8436 (diff) |
Undo optimization: now big chunks of memory are not written as single
memory blocks anymore, but smaller fixed size blocks, so that diffing
can be more effective. For example helps in sculpt mode when making
only local changes to the mesh, previously it would copy the whole
MVert array for each undo step.
Diffstat (limited to 'source/blender/blenloader')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 53 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 30 |
2 files changed, 55 insertions, 28 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ca25f2f0cef..f93b95843d4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -858,6 +858,7 @@ static int fd_read_from_memfile(FileData *filedata, void *buffer, int size) static unsigned int seek= 1<<30; /* the current position */ static unsigned int offset= 0; /* size of previous chunks */ static MemFileChunk *chunk=NULL; + unsigned int chunkoffset, readsize, totread; if(size==0) return 0; @@ -875,29 +876,39 @@ static int fd_read_from_memfile(FileData *filedata, void *buffer, int size) } if(chunk) { - /* first check if it's on the end if current chunk */ - if( seek-offset == chunk->size) { - offset+= chunk->size; - chunk= chunk->next; - } - - /* debug, should never happen */ - if(chunk==NULL) { - printf("illegal read, chunk zero\n"); - return 0; - } - else if( (seek-offset)+size > chunk->size) { - size= chunk->size - (seek-offset); - printf("chunk too large, clipped to %d\n", size); - } - - memcpy(buffer, chunk->buf + (seek-offset), size); - filedata->seek += size; - seek+= size; - - return (size); + totread= 0; + + do { + /* first check if it's on the end if current chunk */ + if(seek-offset == chunk->size) { + offset+= chunk->size; + chunk= chunk->next; + } + + /* debug, should never happen */ + if(chunk==NULL) { + printf("illegal read, chunk zero\n"); + return 0; + } + + chunkoffset= seek-offset; + readsize= size-totread; + + /* data can be spread over multiple chunks, so clamp size + * to within this chunk, and then it will read further in + * the next chunk */ + if(chunkoffset+readsize > chunk->size) + readsize= chunk->size-chunkoffset; + + memcpy(buffer + totread, chunk->buf+chunkoffset, readsize); + totread += readsize; + filedata->seek += readsize; + seek += readsize; + } while(totread < size); + return totread; } + return 0; } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 0804ec9689c..6fcb5312da8 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -187,7 +187,10 @@ Important to know is that 'streaming' has been added to files, for Blender Publi #include <errno.h> -/* ********* my write, buffered writing with minimum 50k chunks ************ */ +/* ********* my write, buffered writing with minimum size chunks ************ */ + +#define MYWRITE_BUFFER_SIZE 100000 +#define MYWRITE_MAX_CHUNK 32768 typedef struct { struct SDNA *sdna; @@ -216,7 +219,7 @@ static WriteData *writedata_new(int file) wd->file= file; - wd->buf= MEM_mallocN(100000, "wd->buf"); + wd->buf= MEM_mallocN(MYWRITE_BUFFER_SIZE, "wd->buf"); return wd; } @@ -256,12 +259,13 @@ int mywfile; * @warning Talks to other functions with global parameters */ -#define MYWRITE_FLUSH NULL +#define MYWRITE_FLUSH NULL static void mywrite( WriteData *wd, void *adr, int len) { if (wd->error) return; + /* flush helps compression for undo-save */ if(adr==MYWRITE_FLUSH) { if(wd->count) { writedata_do_write(wd, wd->buf, wd->count); @@ -272,21 +276,33 @@ static void mywrite( WriteData *wd, void *adr, int len) wd->tot+= len; - if(len>50000) { + /* if we have a single big chunk, write existing data in + * buffer and write out big chunk in smaller pieces */ + if(len>MYWRITE_MAX_CHUNK) { if(wd->count) { writedata_do_write(wd, wd->buf, wd->count); wd->count= 0; } - writedata_do_write(wd, adr, len); + + do { + int writelen= MIN2(len, MYWRITE_MAX_CHUNK); + writedata_do_write(wd, adr, writelen); + adr = (char*)adr + writelen; + len -= writelen; + } while(len > 0); + return; } - if(len+wd->count>99999) { + + /* if data would overflow buffer, write out the buffer */ + if(len+wd->count>MYWRITE_BUFFER_SIZE-1) { writedata_do_write(wd, wd->buf, wd->count); wd->count= 0; } + + /* append data at end of buffer */ memcpy(&wd->buf[wd->count], adr, len); wd->count+= len; - } /** |