I have an asp page that accesses c++ code and gets a xml string returned back. Whenever I access the webpage, I get a timeout in the web browser.
I think I know the problem but am not sure how to fix it. I am not sure how big the xml string will be so I am not sure what size to declare the variable to hold it so I declared iDataBufferSize as the biggest I can make it.
The following function has a for loop which is creating an xml string that gets returned back to the asp code.
The for loop needs to go through about 500 rows and I think when it hits this line wcscat_s(wDataBuffer, iSize, wBuffer);, it starts disk swapping and that slows down the for loop.
I know that when I make iDataBufferSize smaller, it works but I am afraid I will not make the buffer big enough for the xml string.
Thanks
-Dimitry
LPWCH wLargeDataBuffer = 0;
char *cLargeCBuffer = 0;
size_t iDataBufferSize = 93276800;
wLargeDataBuffer = new WCHAR[iDataBufferSize];
cLargeCBuffer = new char[iDataBufferSize];
memset(wLargeDataBuffer, 0, iDataBufferSize);
memset(cLargeCBuffer, 0, iDataBufferSize);
iDataLen = getCServPBJList(wLargeDataBuffer, iDataBufferSize);
int CAdminConsoleInterface::getCServPBJList(LPWCH wDataBuffer, size_t iSize) {
wcscpy_s(wDataBuffer, iSize, L"<jobsList>");
houseKeeper->getCServJobsXML(wDataBuffer, iSize, configHandler->getTextValue (L"UniqueID"), L'P');
wcscat_s(wDataBuffer, iSize, L"</jobsList>");
return wcslen(wDataBuffer);
}
int CHouseKeeper::getCServJobsXML(LPWCH wDataBuffer, size_t iSize, LPWCH wLocation, WCHAR wPrefix) {
WCHAR wIndexPath[1024];
WCHAR wBuffer[1024];
LPWCH wTempBuffer = new WCHAR[16384];
int rc;
char *zErrMsg=0;
char **results;
int nrow=0, ncol=0;
char cSQLDB[1024];
sqlite3 *CServDB;
size_t convertedChars=0;
size_t origsize;
cout << "Looking up CServ jobs." << endl;
getIndexPath(wIndexPath, 1024);
wcscat_s(wIndexPath, 1024, L"CServ.db");
WideCharToMultiByte(CP_UTF8, 0, wIndexPath, -1, cSQLDB, PATH_LENGTH, 0,0);
//cout << "Opening DB: " << cSQLDB << endl;
rc = sqlite3_open(cSQLDB, &CServDB);
if (rc != SQLITE_OK)
{
cout << "Error opening DB." << endl;
return -1;
}
rc = sqlite3_get_table(CServDB, "SELECT * FROM OServ_jobs;", &results, &nrow, &ncol, &zErrMsg);
//cout << "nrow: " << nrow << " - ncol: " << ncol << endl;
for (int i=1; i<=nrow; i++) {
origsize = strlen(results[1+(ncol*i)]) + 1;
mbstowcs_s(&convertedChars, wBuffer, origsize, results[1+(ncol*i)], 1024);
wcscat_s(wDataBuffer, iSize, L"<job id=\"");
wcscat_s(wDataBuffer, iSize, CHelper::escapeXMLData(wBuffer, wTempBuffer, 16384));
wcscat_s(wDataBuffer, iSize, L"\" type=\"");
//wcout << "JobID: " << wBuffer << endl;
origsize = strlen(results[4+(ncol*i)]) + 1;
mbstowcs_s(&convertedChars, wBuffer, origsize, results[4+(ncol*i)], 1024);
wcscat_s(wDataBuffer, iSize, wBuffer);
//wcout << "Type: " << wBuffer << endl;
wcscat_s(wDataBuffer, iSize, L"\">");
origsize = strlen(results[(ncol*i)]) + 1;
mbstowcs_s(&convertedChars, wBuffer, origsize, results[(ncol*i)], 1024);
wcscat_s(wDataBuffer, iSize, L"<currentLocation>");
wcscat_s(wDataBuffer, iSize, wBuffer);
//wcout << "Location: " << wBuffer << endl;
wcscat_s(wDataBuffer, iSize, L"</currentLocation>");
wcscat_s(wDataBuffer, iSize, L"<date>");
origsize = strlen(results[2+(ncol*i)]) + 1;
mbstowcs_s(&convertedChars, wBuffer, origsize, results[2+(ncol*i)], 1024);
wcscat_s(wDataBuffer, iSize, wBuffer);
//wcout << "Date: " << wBuffer << endl;
wcscat_s(wDataBuffer, iSize, L"</date>");
wcscat_s(wDataBuffer, iSize, L"<time>");
origsize = strlen(results[3+(ncol*i)]) + 1;
mbstowcs_s(&convertedChars, wBuffer, origsize, results[3+(ncol*i)], 1024);
wcscat_s(wDataBuffer, iSize, wBuffer);
//wcout << "Time: " << wBuffer << endl;
wcscat_s(wDataBuffer, iSize, L"</time>");
wcscat_s(wDataBuffer, iSize, L"</job>");
memset(wBuffer, 0, 1024);
memset(wTempBuffer, 0, 16384);
}
//wcout << "Data: " << wDataBuffer << endl;
delete []wTempBuffer;
sqlite3_free_table(results);
sqlite3_close(CServDB);
return wcslen(wDataBuffer);
}
There’s an old parable about a man who paints lines down the road. The first hour, he gets 500 feet painted. The next hour, he only gets 300 feet painted. The next hour, only 100 feet. His boss asks him why he’s getting so slow, and he explains that it’s awfully hard to paint when the paint bucket is 1,000 feet away.
You pass each concatenation call a pointer to the beginning of the line. It then has to walk to the line to find the end. Then it makes it a bit bigger. Ouch.
Don’t make so many concatenation calls on such big strings. The simplest fix — use an intermediate buffer. On each iteration of your ‘for’ loop, concatenate into an intermediate buffer. And then use just one call to add that intermediate buffer to the main buffer. Ideally, on the call to add the intermediate buffer to the main buffer, pass a pointer further into the buffer rather than the beginning.
In fact, the best solution is just to use some string class that has an efficient concatenation operation.