Цикл очень медленный и вызывает таймаут asp - PullRequest
1 голос
/ 25 октября 2011

У меня есть страница asp, которая обращается к коду C ++ и возвращает обратно строку xml.Всякий раз, когда я получаю доступ к веб-странице, я получаю тайм-аут в веб-браузере.

Мне кажется, я знаю проблему, но не знаю, как ее исправить.Я не уверен, насколько большой будет строка xml, поэтому я не уверен, какой размер объявлять переменную для ее хранения, поэтому я объявил iDataBufferSize как самое большое, что я могу сделать.

В следующей функции есть цикл for, который создает строку xml, возвращаемую обратно в код asp.

Цикл for должен пройти около 500 строк, и я думаю, что при попаданииэта строка wcscat_s (wDataBuffer, iSize, wBuffer) ;, она запускает замену диска, что замедляет цикл for.

Я знаю, что когда я делаю iDataBufferSize меньше, он работает, но я боюсь, что я не сделаю буфер достаточно большим для строки xml.

Спасибо -Димитрий

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 Ответ

8 голосов
/ 25 октября 2011

Есть старая притча о человеке, который рисует линии на дороге. В первый час он окрашивается в 500 футов. На следующий час он получает только 300 футов. Следующий час всего 100 футов. Его начальник спрашивает его, почему он так медлителен, и объясняет, что рисовать очень трудно, когда ведро с краской находится на расстоянии 1000 футов.

Вы передаете каждый вызов конкатенации указатель на начало строки. Затем он должен идти к линии, чтобы найти конец. Тогда это делает его немного больше. Уч.

Не делайте так много вызовов конкатенации для таких больших строк. Самое простое решение - использовать промежуточный буфер. На каждой итерации цикла for объединяйте в промежуточный буфер. И затем используйте только один вызов, чтобы добавить этот промежуточный буфер в основной буфер. В идеале при вызове добавления промежуточного буфера к основному буферу передайте указатель дальше в буфер, а не в начало.

На самом деле, лучшее решение - это просто использовать какой-нибудь строковый класс с эффективной операцией конкатенации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...