对于循环非常慢并导致asp超时

时间:2011-10-25 03:13:10

标签: c++ visual-c++

我有一个访问c ++代码并获取返回的xml字符串的asp页面。每当我访问网页时,我都会在网络浏览器中超时。

我想我知道这个问题,但我不确定如何解决它。我不确定xml字符串有多大,所以我不确定声明变量的大小,所以我声明iDataBufferSize是我能做到的最大值。

以下函数有一个for循环,它创建一个返回给asp代码的xml字符串。

for循环需要经过大约500行,我认为当它到达这一行wcscat_s(wDataBuffer,iSize,wBuffer);时,它会启动磁盘交换并减慢for循环。

我知道当我使iDataBufferSize更小时,它可以工作,但我担心我不会使缓冲区足够大的xml字符串。

由于 -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);
}

1 个答案:

答案 0 :(得分:8)

有一个关于一个人在路上描绘线条的旧比喻。第一个小时,他画了500英尺。接下来的一个小时,他只画了300英尺。接下来的一个小时,只有100英尺。他的老板问他为什么会这么慢,他解释说当油漆桶在1000英尺以外的时候油漆很难。

您将每个连接调用传递给指向行首的指针。然后它必须走到线路找到结束。然后它让它变得更大。哎哟。

不要在如此大的字符串上进行如此多的串联调用。最简单的修复 - 使用中间缓冲区。在'for'循环的每次迭代中,连接到中间缓冲区。然后只使用一次调用将该中间缓冲区添加到主缓冲区。理想情况下,在调用将中间缓冲区添加到主缓冲区时,将指针进一步传递到缓冲区而不是开头。

实际上,最好的解决方案就是使用一些具有高效串联操作的字符串类。