2011-10-25 136 views
1

私は、C++コードにアクセスしてxml文字列を返すaspページを持っています。 Webページにアクセスするたびに、Webブラウザでタイムアウトになります。ループが非常に遅く、aspにタイムアウトが発生する

私は問題を知っていると思いますが、それを修正する方法がわかりません。私はxml文字列がどれくらい大きいかわからないので、変数を宣言するためにどのようなサイズを指定するかわからないので、最大のiDataBufferSizeを宣言します。

次の関数には、aspコードに返されるxml文字列を作成するforループがあります。

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

道のラインを描いて男についての古い寓話があります。最初の1時間、彼は500フィートのペイントを取得します。次の1時間は、彼は300フィートしか描かれません。次の時間はわずか100フィートです。彼の上司はなぜ彼がなぜそんなに遅くなっているのかを彼に尋ねる。そして彼は塗料バケツが1000フィート離れたところにペイントするのはひどく難しいと説明する。

各連結呼び出しに、行の先頭へのポインタを渡します。それは終わりを見つけるためにラインに歩かなければならない。その後、それは少し大きくなります。ああ。

このような大きな文字列に対しては、あまり多くの連結呼び出しを行わないでください。最も簡単な修正 - 中間バッファを使用します。 'for'ループが繰り返されるたびに、中間バッファに連結します。そして、1つの呼び出しを使用して、その中間バッファをメインバッファに追加します。理想的には、中間バッファをメインバッファに追加する呼び出しで、ポインタを先頭ではなくバッファにさらに渡します。

実際、効率的な連結操作を持つ文字列クラスを使用するのが最善の解決策です。

+1

これはおそらく、ストリングストリームがベビーキャンディのように便利になる場合です。 –

+0

中間バッファはどのくらいの大きさですか?中間バッファで同じ問題が発生しないでしょうか? – ZystemsGo

+0

理想的には、行の最大値より大きい値が可能です。必要に応じて、必要なサイズを過大評価し、必要に応じて再割り当てするための計算をいくつか行うことができます。はい、あなたは同じ問題を作りますが、何度も何度も少なくなります。 (行ごとに15回ではなく、行ごとに1回、問題である巨大なバッファに連結しています) –

関連する問題