FILE_FLAG_OVERLAPPED асинхронная работа с файлом

Тема в разделе "WASM.WIN32", создана пользователем Rascalspb, 20 апр 2008.

  1. Rascalspb

    Rascalspb New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    46
    Адрес:
    СПб
    Впервые пытаюсь работать с файлом в асинхронном режиме. Задача проста - заполнить файл в асинхронном режиме, не дожидаясь заполнения запустить расчет формулы, и выводить время выполнения всех операций.

    Программа создает на диске C файл test.bin размером 120 мб, создает кусками по 40мб (ибо такие куски, как показали эксперименты, пишутся медленно, а мне нужно проверять именно асинхронную запись, поэтому чем медленнее - тем нагляднее).

    Код записи

    Код (Text):
    1. bool CFileWork::WriteAsync(char* file_path, BYTE* data, UINT data_size, UINT buffer_size)
    2. {
    3.     file = CreateFile (file_path,GENERIC_WRITE, FILE_SHARE_READ,NULL,OPEN_ALWAYS, FILE_FLAG_OVERLAPPED,NULL);
    4.     if (file == INVALID_HANDLE_VALUE)
    5.         return false;
    6.  
    7.     events_num = data_size / buffer_size;
    8.     if((data_size%buffer_size)!= 0)
    9.         events_num++;
    10.  
    11.     events = new HANDLE [events_num];
    12.     over = new OVERLAPPED [events_num];
    13.     ZeroMemory(events, sizeof(HANDLE)*events_num);
    14.     ZeroMemory(over, sizeof(OVERLAPPED)*events_num);
    15.  
    16.     DWORD written;
    17.     int i = 0,ev_index=0;
    18.     timer.StartCount();
    19.     for(; i < data_size - buffer_size; i+=buffer_size,ev_index++){
    20.         events[ev_index] = CreateEvent (0, true, false, 0);
    21.         over[ev_index].hEvent = events[ev_index];
    22.         over[ev_index].Offset = i;
    23.         WriteFile (file, data+i, buffer_size, &written, &over[ev_index]);
    24.     }
    25.     events[events_num-1] = CreateEvent (0, true, false, 0);
    26.     over[ev_index].hEvent = events[events_num-1];
    27.     over[ev_index].Offset = i;
    28.     WriteFile (file, data+i, data_size-i, &written, &over[ev_index]);
    29.  
    30.     CloseHandle (file);
    31.     return true;
    32. }
    Вызов всех функций

    Код (Text):
    1.    
    2.  
    3.     UINT data_size = 480 * 1024 * 1024;
    4.     UINT buffer_size = 40*1024*1024;
    5.  
    6.     data = new BYTE [data_size];
    7.     srand (GetTickCount());
    8.     for(int i = 0; i < data_size; i++){
    9.         data[i] = i%256;
    10.     }
    11.         DeleteFile ("c:\\test.bin");
    12.  
    13.     full_timer.StartCount();
    14.     filework.WriteData("c:\\test.bin", data, data_size, buffer_size, true);
    15.     full_timer.StopCount();
    16.     std::cout << "writing initialized.  time is " << full_timer.GetDelta() << " ms\n";
    17.  
    18.     CreateThread(NULL, 0, ThreadWaitOperation, 0, 0, &tid);
    19.  
    20.     calc_timer.StartCount();
    21.     DialogBox(GetModuleHandle(0), (LPCSTR)IDD_MAIN, 0, (DLGPROC)About);
    22.     calc_timer.StopCount();
    23.     full_timer.StopCount();
    24.     std::cout << "calc  time is " << calc_timer.GetDelta() << " ms\n";
    25.     std::cout << "full work time is " << full_timer.GetDelta() << " ms\n";
    и поток ожидания завершения записи

    Код (Text):
    1. DWORD WINAPI ThreadWaitOperation(LPVOID lpParameter)
    2. {
    3.     filework.WaitOperationFinish();
    4.  
    5.     std::cout << "async write finished. time is " << filework.GetTime() << " ms\n";
    6.     return 1;
    7. }
    8.  
    9. bool CFileWork::WaitOperationFinish()
    10. {
    11.     DWORD ret;
    12.     ret =  WaitForMultipleObjects(events_num, events, true, INFINITE);
    13.     timer.StopCount();
    14.     ClearEvents();
    15.     return true;
    16. }
    У меня выполнение явно не асинхронное:
    writing initialized. time is 1898.34 ms
    async write finished. time is 1905.51 ms
    Должно быть время на инициализацию значительно меньше времени всей записи. Кто нибудь может объяснить, в чем дело?
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    помоему при закрытии файла все операции записи явно выполняются. попробуй замерить время выполнения в WriteAsync отдельных кусков, помоему на CloseHandle(file) будет как раз фактическая запись...
     
  3. comrade

    comrade Константин Ёпрст

    Публикаций:
    0
    Регистрация:
    16 сен 2002
    Сообщения:
    232
    Адрес:
    Russian Federation
    Ответ на проблему не знаю, но у тебя есть другаю: коррупция стака. 4-ий параметр для WriteFile (пойнтер lpNumberOfBytesWritten) должен оставатся валидным до конца I/O запроса (т.е. даже до полного completion of asynchronous I/O request).
     
  4. Rascalspb

    Rascalspb New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    46
    Адрес:
    СПб
    writing initialized. time is 19.4853 ms
    async write finished. time is 8115.04 ms

    перенес CloseHandle в часть кода после WaitForMultipleObjects. Как то не очень понятно. Вчера тестил - медленно выполнялась именно WriteFile, управление выходило из него после фактической записи и до CloseHandle управление доходило, када файл полностью записан, как будто венда предвидела, что хэндл клозю сразу после последней записи...

    comrade
    в асинхронной записи этот параметр до лампочки, главное не передавать неверный указатель. Но то что стек убьется - заменил на переменную класса, спасибо =)
     
  5. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    мля, так и возникает мысль о не нужности поиска, т.к. никто не пишет чем все кончилось. Прихожу к мысли, что мне все-таки нужно создавать свою тему (