From 43374a25b92c74d6c566d1b53d47503a28680996 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi <giovanni.bussi@gmail.com> Date: Wed, 28 Aug 2013 19:28:16 +0200 Subject: [PATCH] Optimized OFile Removed many scans of the output buffer by keeping trace of buffer length. Time needed to write a long line with a sequence of file.printf() is now linear with line length. Before it was quatradic, causing problems especially when logging huge atom lists at startup. --- src/tools/OFile.cpp | 25 ++++++++++++++----------- src/tools/OFile.h | 2 ++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/tools/OFile.cpp b/src/tools/OFile.cpp index 7820ee202..5ff9a73a1 100644 --- a/src/tools/OFile.cpp +++ b/src/tools/OFile.cpp @@ -53,6 +53,7 @@ OFile::OFile(): { fmtField(); buflen=1; + actual_buffer_length=0; buffer=new char[buflen]; // these are set to zero to avoid valgrind errors for(unsigned i=0;i<buflen;++i) buffer[i]=0; @@ -78,14 +79,13 @@ OFile& OFile::setLinePrefix(const std::string&l){ } int OFile::printf(const char*fmt,...){ - size_t pointer=strlen(buffer); va_list arg; va_start(arg, fmt); - int r=std::vsnprintf(&buffer[pointer],buflen-pointer,fmt,arg); + int r=std::vsnprintf(&buffer[actual_buffer_length],buflen-actual_buffer_length,fmt,arg); va_end(arg); - if(r>=buflen-pointer){ + if(r>=buflen-actual_buffer_length){ int newlen=buflen; - while(newlen<=r+pointer) newlen*=2; + while(newlen<=r+actual_buffer_length) newlen*=2; char* newbuf=new char [newlen]; memmove(newbuf,buffer,buflen); for(int k=buflen;k<newlen;k++) newbuf[k]=0; @@ -94,22 +94,25 @@ int OFile::printf(const char*fmt,...){ buflen=newlen; va_list arg; va_start(arg, fmt); - r=std::vsnprintf(&buffer[pointer],buflen-pointer,fmt,arg); + r=std::vsnprintf(&buffer[actual_buffer_length],buflen-actual_buffer_length,fmt,arg); va_end(arg); } - plumed_massert(r>-1 && r<buflen-pointer,"error using fmt string " + std::string(fmt)); + plumed_massert(r>-1 && r<buflen-actual_buffer_length,"error using fmt string " + std::string(fmt)); // Line is buffered until newline, then written with a PLUMED: prefix char*p1=buffer; char*p2; - while((p2=strchr(p1,'\n'))){ - *p2='\0'; +// newline is only searched in the just added portion: + char*psearch=p1+actual_buffer_length; + actual_buffer_length+=r; + while((p2=strchr(psearch,'\n'))){ if(linePrefix.length()>0) llwrite(linePrefix.c_str(),linePrefix.length()); - llwrite(p1,std::strlen(p1)); - llwrite("\n",1); + llwrite(p1,p2-p1+1); + actual_buffer_length-=(p2-p1)+1; p1=p2+1; + psearch=p1; }; - memmove(buffer,p1,strlen(p1)+1); + if(buffer!=p1) memmove(buffer,p1,actual_buffer_length); return r; } diff --git a/src/tools/OFile.h b/src/tools/OFile.h index 74732c167..fe08c9dce 100644 --- a/src/tools/OFile.h +++ b/src/tools/OFile.h @@ -92,6 +92,8 @@ public virtual FileBase{ char* buffer; /// Internal buffer length int buflen; +/// This variables stores the actual buffer length + unsigned actual_buffer_length; /// Class identifying a single field for fielded output class Field: public FieldBase{ -- GitLab