This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
Re: [PATCH] Speed-up sprintf() family of functions.
- From: Sergei Organov <osv at javad dot com>
- To: ecos-patches at ecos dot sourceware dot org
- Date: Wed, 17 Jan 2007 14:12:03 +0300
- Subject: Re: [PATCH] Speed-up sprintf() family of functions.
- References: <87fyb3x070.fsf@javad.com> <459529B0.8080407@eCosCentric.com> <87wt4allsq.fsf@javad.com> <4596F7EA.4090605@eCosCentric.com> <877iw5kw4k.fsf@javad.com> <459BCA9A.1030007@eCosCentric.com>
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 */
}