Solved

need better performance than sprintf gives

Posted on 1998-12-21
5
1,585 Views
Last Modified: 2009-07-29
I am writing a C program using Visual C/C++ under NT 4.0. Performance is critical.

Some basic tests indicate that sprintf() is a performance dog.  Are there any other ways to format data that are performance friendly?  

What my code does (at a very high level):  my code loops. Each iteration I process a number of different fields (of various data types: int, long, string, etc), contatenating the formatted results to a single text buffer.

I need to sprintf each field individualy rather than a single sprintf for all the fields because for each iteration of the loop it is not known what fields are involved (in fact, each iteration is likely to have a different set of fields).

What I mean by contatenate.....

  Offset = 0;
  Count = sprintf(Buffer, "%d", int_variable);
  Offset += Count;
  Count = sprintf(Buffer + Offset, "%5ld", long_variable);
  Offset += Count;
  Count = sprintf(Buffer + Offset, "%10s", string_variable);
  Offset += Count;
  Buffer[Offset] = '\n';

0
Comment
Question by:msaccess
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
5 Comments
 
LVL 3

Expert Comment

by:marcjb
ID: 1255359
First, the last line you have:

Buffer[Offset] = '\n';

clobbers the null terminator, and you will most likely end up with garbage at the end of the string.  You may want to add:

Buffer[Offset+1] = '\0';

Now, other that sprintf, you could try converting the numbers to strings using a hand coded itoa function (since the itoa function is not ANSI C).  You could then copy this string to the Buffer string using a loop, but I think that this would actually take longer than the sprintf function.

Also, you mentioned that you could not use a single sprintf function because it would not be known what combination of fields would be used.  If the total number of combinations is realatively small, you might consider using a single sprintf inside a few if .. else control blocks:
  if ( /*field 1 and field 2*/ )
      sprintf( /* field 1 and field 2 */
  else if ( /* field 1 */ )
      sprintf( /* field 1 */)
  /* and so on */
 
Of course, if there are a number of fields, this quickly becomes impractical.  Hope this helps,

Marc
0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1255360
I would think the main performance limit of sprintf is parsing the format string.

If you use functions which don't require parsing, this should be faster.

Even these functions can be improved with hand code functions which know exactly what kind of data your working with.

Writing you own itoa is not strictly necessary, there is an MS extension _itoa, but it might worth it.

Before you start coding again, I assume you have used the profiler (or another technique other than guess work) and confirmed that sprintf is really is the function that is slowing your program down.
0
 
LVL 3

Expert Comment

by:NullTerminator
ID: 1255361
If you think condensing the printf calls to one would help, here is a snippet that might help

// note this is off the top of my head so you may have
// to tweak it a bit, but you get the idea

char *pFmt = NULL;
char *pArgs = NULL; // maybe void* will do

int offset = 0;

// run one iteration to find record size
// allocate enough space for record
pArgs = (char*)malloc( N );
// allocate space for format string at, say 5 x field count
pFmt = malloc( FieldCount * 5)

while(got more fields) {
switch( fieldType ){
      case INT_FIELD:
            strcat(pFmt, "%5d");
            *(int*)(pArgs + offset) = valueOfField;
            offset += sizeof(int);
            break;
      case DOUBLE_FIELD:
            strcat(pFmt, "%5.2f");
            *(double*)(pArgs + offset) = valueOfField;
            offset += sizeof(double);
            break;
      case ETC:
            do other types
      }      // end switch
}      // end while

// not that strcat can easily be optimized with
// use of an offset and pointer arithmentic as well

// pass the data to vsprintf in one shot
// vsprintf will continue digging into pArgs, as long
// as pFmt specifiers need to be matched.
vsprintf(Buffer, pFmt, pArgs);

'\0'
0
 
LVL 10

Accepted Solution

by:
rbr earned 200 total points
ID: 1255362
I think this would be already faster since only one sprintf call is used
sprintf(Buffer, "%d%5ld%10s\n", int_variable,long_variable,string_variable);

Another way is to use itoa and ltoa but they are not ANSI, or you have to write your own function.
e.g.

my_itoa (char *buffer,int number)
{
   unsigned int temp;
   char b,*pstart,*pend;
   int i=0;
   if (number=0)
      strcpy (buffer;"0");
   else {
         temp=abs(number)
         while (temp > 0) {
                  buffer[i++]='0'+temp%10;
            temp/=10;
         }
     if (number<0)
            buffer[i++]='-';
      buffer[i]=0;
     pstart=buffer;
     pend=&(buffer[i-1]);
      i/=2;
     
     for (;i>0;i--,pstart++,pend--) {
        b=*pstart
        *pstart=*pend;
        *pend=b;
      }
}      
       
0
 

Author Comment

by:msaccess
ID: 1255363
All good and helpful suggestions.  But special thanks to
NullTerminator -- initial indications are that your idea will
help me a great deal.

Thanks to everyone for taking the time to help!!!!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The goal of this video is to provide viewers with basic examples to understand and use pointers in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question