Mercurial > nand-ecoscentric
changeset 2356:52c6a8ead2a6
Speed-up [v]s[n]printf() functions by a factor of about 2+. In
particular, sprintf(s, "%s", "") becomes faster 2.8 times,
printing of every character -- 1.7 times, and, as a result, e.g.,
printing of a string of length 50 -- 2.2 times.
* include/stream.hxx (class Cyg_OutputStream): New ABC.
(class Cyg_StdioStream): inherit from Cyg_OutputStream; make
the destructor, write(), and get_error() virtual.
* src/output/vfnprintf.cxx (vfnprintf): Use ABC Cyg_OutputStream
instead of Cyg_StdioStream.
* src/common/vsnprintf.cxx (class Cyg_VsnprintfStream): New class
that specializes Cyg_OutputStream for output to a string.
(vsnprintf): Use Cyg_VsnprintfStream for printing to a string.
| author | asl |
|---|---|
| date | Sat, 27 Jan 2007 13:53:37 +0000 |
| parents | 460b70d39a50 |
| children | c1c9f81e3995 |
| files | packages/language/c/libc/stdio/current/ChangeLog packages/language/c/libc/stdio/current/include/stream.hxx packages/language/c/libc/stdio/current/src/common/stream.cxx packages/language/c/libc/stdio/current/src/common/vsnprintf.cxx packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx |
| diffstat | 5 files changed, 90 insertions(+), 77 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/language/c/libc/stdio/current/ChangeLog +++ b/packages/language/c/libc/stdio/current/ChangeLog @@ -1,3 +1,21 @@ +2007-01-16 Sergei Organov <osv@javad.com> + + Speed-up [v]s[n]printf() functions by a factor of about 2+. In + particular, sprintf(s, "%s", "") becomes faster 2.8 times, + printing of every character -- 1.7 times, and, as a result, e.g., + printing of a string of length 50 -- 2.2 times. + + * include/stream.hxx (class Cyg_OutputStream): New ABC. + (class Cyg_StdioStream): inherit from Cyg_OutputStream; make + the destructor, write(), and get_error() virtual. + + * src/output/vfnprintf.cxx (vfnprintf): Use ABC Cyg_OutputStream + instead of Cyg_StdioStream. + + * src/common/vsnprintf.cxx (class Cyg_VsnprintfStream): New class + that specializes Cyg_OutputStream for output to a string. + (vsnprintf): Use Cyg_VsnprintfStream for printing to a string. + 2006-12-22 Sergei Organov <osv@javad.com> * src/output/vfnprintf.cxx (vfnprintf): Speed-up formatting of
--- a/packages/language/c/libc/stdio/current/include/stream.hxx +++ b/packages/language/c/libc/stdio/current/include/stream.hxx @@ -73,11 +73,28 @@ // TYPE DEFINITIONS +class Cyg_OutputStream +{ +public: + + // Provide empty virtual destructor + virtual ~Cyg_OutputStream() {} + + // The following two functions aren't made pure virtual not to bring + // dependency on C++ runtime to every application. + + virtual Cyg_ErrNo write( const cyg_uint8 *buffer, cyg_ucount32 buffer_length, + cyg_ucount32 *bytes_written ); + + virtual Cyg_ErrNo get_error( void ); + +}; + class Cyg_StdioStream; __externC Cyg_ErrNo cyg_libc_stdio_flush_all_but( Cyg_StdioStream * ); -class Cyg_StdioStream +class Cyg_StdioStream: public Cyg_OutputStream { friend int setvbuf( FILE *, char *, int, size_t ) __THROW; friend Cyg_ErrNo @@ -207,7 +224,7 @@ private: public: // DESTRUCTOR - + virtual ~Cyg_StdioStream(); @@ -253,7 +270,7 @@ public: cyg_ucount32 bytes_available_to_read( void ); - Cyg_ErrNo + virtual Cyg_ErrNo write( const cyg_uint8 *buffer, cyg_ucount32 buffer_length, cyg_ucount32 *bytes_written ); @@ -284,7 +301,7 @@ public: unlock_me( void ); // get error status for this file - Cyg_ErrNo + virtual Cyg_ErrNo get_error( void ); // set error status for this file.
--- a/packages/language/c/libc/stdio/current/src/common/stream.cxx +++ b/packages/language/c/libc/stdio/current/src/common/stream.cxx @@ -720,4 +720,25 @@ Cyg_StdioStream::write( const cyg_uint8 return write_err; } // write() +// +// class Cyg_OutputStream +// + +Cyg_ErrNo +Cyg_OutputStream::write( const cyg_uint8 *buffer, cyg_ucount32 buffer_length, + cyg_ucount32 *bytes_written ) +{ + CYG_FAIL("Cyg_OutputStream::write(): pure virtual called"); + return ENOSYS; +} + +Cyg_ErrNo +Cyg_OutputStream::get_error( void ) +{ + CYG_FAIL("Cyg_OutputStream::get_error(): pure virtual called"); + return ENOSYS; +} + + + // EOF stream.cxx
--- a/packages/language/c/libc/stdio/current/src/common/vsnprintf.cxx +++ b/packages/language/c/libc/stdio/current/src/common/vsnprintf.cxx @@ -61,92 +61,49 @@ #include <stddef.h> // NULL and size_t from compiler #include <stdio.h> // header for this file #include <errno.h> // error codes -#include <cyg/io/devtab.h> // Device table #include <cyg/libc/stdio/stream.hxx>// Cyg_StdioStream #include <cyg/libc/stdio/io.inl> // I/O system inlines -#ifndef CYGPKG_LIBC_STDIO_FILEIO - // FUNCTIONS -static Cyg_ErrNo -str_write(cyg_stdio_handle_t handle, const void *buf, cyg_uint32 *len) +class Cyg_VsnprintfStream: public Cyg_OutputStream { - cyg_devtab_entry_t *dev = (cyg_devtab_entry_t *)handle; - cyg_uint8 **str_p = (cyg_uint8 **)dev->priv; - cyg_ucount32 i; +public: + Cyg_VsnprintfStream(char* s): s_(s) {} + + virtual ~Cyg_VsnprintfStream() { *s_ = '\0'; } - // I suspect most strings passed to vsnprintf will be relatively short, - // so we just take the simple approach rather than have the overhead - // of calling memcpy etc. + virtual Cyg_ErrNo write( const cyg_uint8 *buffer, + cyg_ucount32 buffer_length, cyg_ucount32 *bytes_written ); - // simply copy string until we run out of user space + virtual Cyg_ErrNo get_error( void ) { return ENOERR; } + +private: + char* s_; +}; - for (i = 0; i < *len; i++, (*str_p)++ ) - { - **str_p = *((cyg_uint8 *)buf + i); - } // for - - *len = i; - +Cyg_ErrNo +Cyg_VsnprintfStream::write( + const cyg_uint8 *buffer, + cyg_ucount32 buffer_length, + cyg_ucount32 *bytes_written ) +{ + char *dest = s_; + char const *src = (char const *)buffer; + char const *end = src + buffer_length; + while(src < end) + *dest++ = *src++; + s_ = dest; + *bytes_written = buffer_length; return ENOERR; - -} // str_write() - -static DEVIO_TABLE(devio_table, - str_write, // write - NULL, // read - NULL, // select - NULL, // get_config - NULL); // set_config +} externC int vsnprintf( char *s, size_t size, const char *format, va_list arg ) __THROW { - int rc; - // construct a fake device with the address of the string we've - // been passed as its private data. This way we can use the data - // directly - DEVTAB_ENTRY_NO_INIT(strdev, - "strdev", // Name - NULL, // Dependent name (layered device) - &devio_table, // I/O function table - NULL, // Init - NULL, // Lookup - &s); // private - Cyg_StdioStream my_stream( &strdev, Cyg_StdioStream::CYG_STREAM_WRITE, - false, false, _IONBF, 0, NULL ); - - rc = vfnprintf( (FILE *)&my_stream, size, format, arg ); - - // Null-terminate it, but note that s has been changed by str_write(), so - // that it now points to the end of the string - s[0] = '\0'; - - return rc; - + Cyg_VsnprintfStream stream(s); + return vfnprintf( (FILE *)(void *)&stream, size, format, arg ); } // vsnprintf() -#else - -externC int -vsnprintf( char *s, size_t size, const char *format, va_list arg ) __THROW -{ - int rc; - - Cyg_StdioStream my_stream( Cyg_StdioStream::CYG_STREAM_WRITE, - size, (cyg_uint8 *)s ); - - rc = vfnprintf( (FILE *)&my_stream, size, format, arg ); - - if( rc > 0 ) - s[rc] = '\0'; - - return rc; - -} // vsnprintf() - -#endif - // EOF vsnprintf.cxx
--- a/packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx +++ b/packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx @@ -210,7 +210,7 @@ vfnprintf ( FILE *stream, size_t n, cons #define PRINT(ptr, len) \ CYG_MACRO_START \ cyg_ucount32 length = MIN( (cyg_ucount32) len, n - ret - 1); \ - if (((Cyg_StdioStream *)stream)->write( (const cyg_uint8 *)ptr, \ + if (((Cyg_OutputStream *)stream)->write( (const cyg_uint8 *)ptr, \ length, &length )) \ goto error; \ if (length < (cyg_ucount32)len) { \ @@ -672,7 +672,7 @@ number: if ((dprec = pre } done: error: - return (((Cyg_StdioStream *) stream)->get_error() ? EOF : ret); + return (((Cyg_OutputStream *) stream)->get_error() ? EOF : ret); /* NOTREACHED */ }
