This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Speed-up sprintf() family of functions.


Jonathan Larmour <jifl@eCosCentric.com> writes:
[...]
> If you could repost the patch with the changes we did agree on, that
> would be great, thanks. Although I won't be able to commit it before
> your copyright assignment arrives.

The updated patch is attached.

As for the copyright assignment, according to DHL, it has been delivered
to you Monday morning.

-- Sergei Organov.

Index: packages/language/c/libc/stdio/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/language/c/libc/stdio/current/ChangeLog,v
retrieving revision 1.39
diff -u -a -r1.39 ChangeLog
--- packages/language/c/libc/stdio/current/ChangeLog	22 Dec 2006 21:37:00 -0000	1.39
+++ packages/language/c/libc/stdio/current/ChangeLog	16 Jan 2007 14:37:13 -0000
@@ -1,3 +1,22 @@
+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
Index: packages/language/c/libc/stdio/current/include/stream.hxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/language/c/libc/stdio/current/include/stream.hxx,v
retrieving revision 1.7
diff -u -a -r1.7 stream.hxx
--- packages/language/c/libc/stdio/current/include/stream.hxx	29 Mar 2004 11:24:38 -0000	1.7
+++ packages/language/c/libc/stdio/current/include/stream.hxx	16 Jan 2007 14:37:16 -0000
@@ -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 @@
 public:
     
     // DESTRUCTOR
-
+    virtual
     ~Cyg_StdioStream();
 
 
@@ -253,7 +270,7 @@
     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 @@
     unlock_me( void );
 
     // get error status for this file 
-    Cyg_ErrNo
+    virtual Cyg_ErrNo
     get_error( void );
 
     // set error status for this file.
Index: packages/language/c/libc/stdio/current/src/common/stream.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/language/c/libc/stdio/current/src/common/stream.cxx,v
retrieving revision 1.10
diff -u -a -r1.10 stream.cxx
--- packages/language/c/libc/stdio/current/src/common/stream.cxx	26 Sep 2006 18:51:22 -0000	1.10
+++ packages/language/c/libc/stdio/current/src/common/stream.cxx	16 Jan 2007 14:37:16 -0000
@@ -720,4 +720,25 @@
     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
Index: packages/language/c/libc/stdio/current/src/common/vsnprintf.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/language/c/libc/stdio/current/src/common/vsnprintf.cxx,v
retrieving revision 1.4
diff -u -a -r1.4 vsnprintf.cxx
--- packages/language/c/libc/stdio/current/src/common/vsnprintf.cxx	15 Mar 2004 15:21:44 -0000	1.4
+++ packages/language/c/libc/stdio/current/src/common/vsnprintf.cxx	16 Jan 2007 14:37:16 -0000
@@ -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;
-
-    // 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.
-
-    // simply copy string until we run out of user space
-
-    for (i = 0; i < *len; i++, (*str_p)++ )
-    {
-        **str_p = *((cyg_uint8 *)buf + i);
-    } // for
-
-    *len = i;
-
-    return ENOERR;
-    
-} // str_write()
+public:
+    Cyg_VsnprintfStream(char* s): s_(s) {}
 
-static DEVIO_TABLE(devio_table,
-                   str_write,       // write
-                   NULL,            // read
-                   NULL,            // select
-                   NULL,            // get_config
-                   NULL);           // set_config
+    virtual ~Cyg_VsnprintfStream() { *s_ = '\0'; }
 
-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';
+    virtual Cyg_ErrNo write( const cyg_uint8 *buffer,
+        cyg_ucount32 buffer_length, cyg_ucount32 *bytes_written );
 
-    return rc;
+    virtual Cyg_ErrNo get_error( void ) { return ENOERR; }
 
-} // vsnprintf()
+private:
+    char* s_;
+};
 
-#else
+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;
+}
 
 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;
-
+    Cyg_VsnprintfStream stream(s);
+    return vfnprintf( (FILE *)&stream, size, format, arg );
 } // vsnprintf()
 
-#endif
-
 // EOF vsnprintf.cxx
Index: packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx,v
retrieving revision 1.10
diff -u -a -r1.10 vfnprintf.cxx
--- packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx	2 Jan 2007 11:54:37 -0000	1.10
+++ packages/language/c/libc/stdio/current/src/output/vfnprintf.cxx	16 Jan 2007 14:37:18 -0000
@@ -210,7 +210,7 @@
 #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 @@
         }
 done:
 error:
-        return (((Cyg_StdioStream *) stream)->get_error() ? EOF : ret);
+        return (((Cyg_OutputStream *) stream)->get_error() ? EOF : ret);
         /* NOTREACHED */
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]