Click to See Complete Forum and Search --> : CString so slow


August 27th, 1999, 01:14 PM
I have a big string to construct from separate pieces using the following code:

CString str;
for (int idx = 0; idx < nbrItems; idx++)
{
str += items[idx];
}

This code gets extremely slow when nbrItems is > 1000. I guess this is because memory needs to be reallocated every time.

I ended up allocating memory large enough to hold the entire string, construct using strcpy() and then assign this buffer to CString. This works fast.

Is there a better way to do this. The reason for using CString is because I'm setting up variable for CEdit control.

Thanks

Dave Coleman
August 27th, 1999, 01:33 PM
Looks like you've got the most effective way of doing this. Do all of your items[] contain a value? Maybe skipping them if they are empty might speed it up a little.

I agree that while it's inefficient, allocating memory for the entire string is the fastest way. Re-allocating memory is slow.

Good Luck

Rail Jon Rogut
August 27th, 1999, 03:23 PM
If you preallocate the memory, and change your code to the following, you'll be able to do it much faster:

register int idx2;

char items[20000];
int nbrItems = 20000;

// Fill items with some data

for (int iIndex = 0; iIndex < nbrItems; iIndex++)
items = 'A';

// AfxMessageBox("Start");

// Your code - on my system takes about 10 to 11 seconds

CString str;

for (int idx = 0; idx < nbrItems; idx++)
{
str += items[idx];
}

// AfxMessageBox("Done");

// My code - on my system takes about 1 seconds (or less)

char* pItems = &items[0];

CString str2(' ', nbrItems);

for (idx2 = 0; idx2 < nbrItems; idx2++)
{
str2.SetAt(idx2, *(pItems + idx2));
}

// AfxMessageBox("Done");


Rail

------------
Recording Engineer/Software Developer
[i]Rail Jon Rogut Software
http://home.earthlink.net/~railro/
railro@earthlink.net

Dave Coleman
August 27th, 1999, 03:58 PM
Thank you. I thought there was something, but I couldn't think of anything.

DC

August 27th, 1999, 04:06 PM
Actually, items on my code is array of pointers to strings.

/* for example */
char *items[20000];
items[0] = strdup("hello");
.
.
.

and each string can be of any length (in my program, they are about 50 characters long).

Thanks

Dmitriy
August 27th, 1999, 04:18 PM
1) Find summary of all string length
2) allocate memory
3) strcpy()
4) constructor CString()

It seems to me you've solved the problem in the same way.

I think standart string manipulation functions always work faster then CString just because CString use them.


Dmitriy, MCSE

Rail Jon Rogut
August 27th, 1999, 07:38 PM
This should work then:

register int idx2;
register unsigned int j;

char szStrings[2000][256];

char *items[2000];

int nbrItems = 2000;

for (idx2 = 0; idx2 < nbrItems; idx2++)
{
strcpy (szStrings, "Temporary String entered here");

items[idx2] = strdup(szStrings[idx2]);
}

AfxMessageBox("Start");

DWORD dwLength = 0;
DWORD dwPosition = 0;

// Get the total length of the new CString

for (idx2 = 0; idx2 < nbrItems; idx2++)
{
dwLength += strlen(items[idx2]);
}

CString str2(' ', dwLength);

unsigned int iLength = 0;

for (idx2 = 0; idx2 < nbrItems; idx2 ++)
{
// For VC++ 6.x possibly use CString::Insert()

iLength = strlen(items[idx2]);

for (j = 0; j < iLength; j++)
str2.SetAt((dwPosition + j), *(items[idx2] + j));

dwPosition += iLength;
}

AfxMessageBox("Done");

for (idx2 = 0; idx2 < nbrItems; idx2++)
{
free(items[idx2]);
}


Rail

------------
Recording Engineer/Software Developer
[i]Rail Jon Rogut Software
http://home.earthlink.net/~railro/
railro@earthlink.net

Dmitriy
August 27th, 1999, 09:45 PM
May be replace
CString str2(' ', dwLength);

unsigned int iLength = 0;

for (idx2 = 0; idx2 < nbrItems; idx2 ++)
{
// For VC++ 6.x possibly use CString::Insert()

iLength = strlen(items[idx2]);

for (j = 0; j < iLength; j++)
str2.SetAt((dwPosition + j), *(items[idx2] + j));

dwPosition += iLength;
}


by

char* lpBuf=(char*) calloc(dwLength+1,1);

for (idx2 = 0; idx2 < nbrItems; idx2 ++)
strcat(lpBuf,items[idx2]);
CString str(lpBuf);
free((void*) lpBuf);


Dmitriy, MCSE

August 27th, 1999, 10:01 PM
Thanks alot. By setting the initial size of CString to the total length of strings and filling out the buffer saves the need for allocating another buffer that holds the entire string. Although we have virtual memory on Win32, it is always good to save memory if possible. I can hear page file swapping as the buffer grows.

Rail Jon Rogut
August 28th, 1999, 01:06 AM
That would still use twice as much memory, which is very similar to what he was already doing. I would probably reduce my code down to:

CString str2(' ', dwLength);

for (idx2 = 0; idx2 < nbrItems; idx2++)
{
for (j = 0; j < strlen(items); j++)
str2.SetAt(dwPosition++, *(items[idx2] + j));
}

Heck, I'd probably use the same DWORD variable for dwLength and dwPosition.

Best regards.

Rail

------------
Recording Engineer/Software Developer
[i]Rail Jon Rogut Software
http://home.earthlink.net/~railro/
railro@earthlink.net