2011-10-25 37 views
1

我有一个asp页面访问C++代码,并得到一个xml字符串返回。无论何时访问网页,我都会在Web浏览器中看到超时。For循环非常缓慢,并导致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

请使用'std :: string'或'std :: vector';从来不删除东西。 – GManNickG

回答

8

有关于一个男人谁画线的道路旧的比喻。第一个小时,他画了500英尺。接下来的一小时,他只画了300英尺。下一个小时,只有100英尺。他的老板问他为什么如此缓慢,他解释说,当油漆桶距离1000英尺远时,很难画。

您将每个串联调用传递给该行开头的指针。然后它必须走到线路才能找到结束点。然后它变得更大一点。哎哟。

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

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

+1

也许在这种情况下,串流可能来得方便,就像婴儿糖果一样。 – 2011-10-25 03:27:23

+0

我会制作中间缓冲区的大小是多少?我不会遇到与中间缓冲区相同的问题吗? – ZystemsGo

+0

理想情况下,比最大的行可能会更大。如有必要,您可以进行一些数学运算来高估所需的大小,并在需要时重新分配。是的,你会创造同样的问题,但少了许多倍。 (每行只有一次,而不是每行15次,它连接到巨大的缓冲区就是问题了。) –