[WinXP] Чтение больших файлов. > 200 МБайт.

Тема в разделе "WASM.WIN32", создана пользователем MuForum, 5 май 2010.

  1. Phyber

    Phyber New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2010
    Сообщения:
    96
    Маппинг для понта. к слову про якобы необходимость включать 3Гб в винде.

    http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
     
  2. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Вот здесь написан ОБЩИЙ алгоритм действий. А как ты его будешь реализовывать это уже твое дело. А почему построчный? А все потому, что изначально в задании написано:
    Ну вот и делай чтение небольшой части (substrsize*2) в буфер, и при этом чтении проверяй вхождение туда требуемого текста. если нашел, то дальше читай файл до нахождения конца строки, а потом выводи прочитанный буфер (строку содержащую часть текста) на экран. Ну и очищай его, для дальнейшего чтения.

    полезно будет
     
  3. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    Ребята, а что скажите о таком алгоритме?
    Код (Text):
    1. void _fastcall TFFMain::LoadDataFromFile(AnsiString sFilePath, AnsiString sSearchText, bool bMatchCase)
    2.  
    3. {
    4.  
    5.     if ( FileExists(sFilePath) == false )
    6.  
    7.     {
    8.  
    9.         return;
    10.  
    11.     }
    12.  
    13.     // ----
    14.  
    15.     long seek                   = 0;
    16.  
    17.     long nStart                 = 0;
    18.  
    19.     long nPos                   = 0;
    20.  
    21.     std::string str             = "";
    22.  
    23.     std::string strtemp         = "";
    24.  
    25.     std::string sFindLine       = "";
    26.  
    27.     // ----
    28.  
    29.     int iRes                    = 0;
    30.  
    31.     // ----
    32.  
    33.     const int iMaxReadLength    = 16384; // 2^14 = 16384;
    34.  
    35.     // ----
    36.  
    37.     long fd     = open(sFilePath.c_str(), O_RDONLY | O_BINARY);
    38.  
    39.     // ----
    40.  
    41.     if(fd != -1)
    42.  
    43.     {
    44.  
    45.         sFindLine   = sSearchText.c_str();
    46.  
    47.         // ----
    48.  
    49.         str.resize(iMaxReadLength);
    50.  
    51.         // ----
    52.  
    53.         lseek(fd, 0, SEEK_SET); // Set Start Position;
    54.  
    55.         // ----
    56.  
    57.         while( (iRes = read(fd, (void*) & str.data()[0], iMaxReadLength)) > 0 )
    58.  
    59.         {
    60.  
    61.             nStart  = 0;
    62.  
    63.             // ----
    64.  
    65.             while(true)
    66.  
    67.             {
    68.  
    69.                 nPos    = str.find("\n", nStart);
    70.  
    71.                 // ----
    72.  
    73.                 if (nPos < 1)
    74.  
    75.                 {
    76.  
    77.                     break;
    78.  
    79.                 }
    80.  
    81.                 // ----
    82.  
    83.                 strtemp = str.substr(nStart, nPos - nStart);
    84.  
    85.                 // ----
    86.  
    87.                 if(strtemp.find(sFindLine) != strtemp.npos)
    88.  
    89.                 {
    90.  
    91.                     m_log->Lines->Append(strtemp.c_str());
    92.  
    93.                     //rec.push_back(str);
    94.  
    95.                 }
    96.  
    97.                 // ----
    98.  
    99.                 seek    += strtemp.length() + 1;
    100.  
    101.                 // ----
    102.  
    103.                 nStart  = seek;
    104.  
    105.             }
    106.  
    107.             // ----
    108.  
    109.             str.resize(iMaxReadLength);
    110.  
    111.             // ----
    112.  
    113.             lseek(fd, seek, SEEK_SET);
    114.  
    115.         }
    116.  
    117.     }
    118.  
    119.     // ----
    120.  
    121.     close(fd);
    122.  
    123.     // ----
    124.  
    125.     str.clear();
    126.  
    127.     strtemp.clear();
    128.  
    129.     sFindLine.clear();
    130.  
    131. }
    - Логи размеров 50 метров обрабатываются за 30-32 секунды на моём компе.
    - Честно говоря меня это всё равно не очень устраивает =(
    - Может можно ещё как-то улучшить этот показатель?
    - Что-то оптимизировать или изменить алгоритм на более производительный.


    P.S. -> В общем прошу помощи.
     
  4. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    http://www.everfall.com/paste/id.php?z06zv915lpyq
    - Вот собственно то, что у меня пока получилось.
    - Если кто может, жду комментов по алгоритму, может какие-то совету/оптимизации и т.д.
     
  5. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    http://www.everfall.com/paste/id.php?24p7x6n0jnzn
    - Больше оптимизация я пока не вижу.


    P.S. -> Есть у кого-то ещё какие-то идеи?
     
  6. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    MuForum
    судя по тому что вы используете билдер, кроссплатформенность вам не нужна.
    значит самым производительным решением будет использование winapi
    конкретно ReadFile в асинхронном варианте (overlapped IO)
    читать кусками по n*512 байт (512 == размер кластера)
    искать своей функцией которая обработает конец буфера
    при асинхронном чтении пока кусок файла читается, в уже загруженном куске будет искаться
     
  7. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    искать проще регуляркой типа
    ^(.*?sys.*?)$
     
  8. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    еще в самом начале грэйт все правильно сказал. мемори маппинг - самый быстрый способ работы с файлами.
    дело в том, что любая выделенная виртуальная память является мемори маппед файлом. те, если вы не мапите нужный вам файл, то мапите своп и читаете в него ваш файл. причем, к этому может может добавиться работа с кучей, чего нет при прямом маппинге.
    и с чего вы решили, что при маппинге будет читаться весь файл, а не только тот кусок, что вы укажете?

    регулярки - тормозная вещь. но тут зависит что вы искать желаете.
     
  9. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    Регулярные выражения - вещь медленная. (Удобная, но медленная, так что отпадает)

    - Написать программу мне нужно пока только под следующие платформы: Windows XP, 2003, Vista, 2008, Seven.

    P.S. -> Ещё я прочитал в одном месте, что очень быстро получится читать если открывать файл с помощью функции CreateFile с флагом "FILE_FLAG_NO_BUFFERING" и сделать буфер для чтения 8 МБайт, то скорость будет одна из самых быстрых.
    - Прочитал я это в этом сообщении: Перейти;
    - Я хотел попробовать так сделать, но я не знаю как передвигать каретку/маркер в файле если использовать функцию CreateFile().
     
  10. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    ReadFile() сам всё передвинет :)
    воообще задача тривиальная, буквально 10 строк кода.
     
  11. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    http://msdn.microsoft.com/en-us/library/aa365541%28VS.85%29.aspx
     
  12. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    mrcrown
    Читать по несколько байт из файла ?! При том что даже из ОЗУ в кэш данные передаются по 64 или 128 байт, а с диска читаются и вовсе килобайтами ?! Тратить по несколько сотен тактов на каждый переход юзер<->кернел в то время как сам перебор символов занимает пару тактов на байт ?!! Супероптимизация

    Вообще не понимаю о чем тут можно рассуждать, если есть два стандартных подхода - либо MMF, либо чтение блоками размером порядка (8-32)К. По скорости они практически одинаковы и разница м.б. только в удобстве использования (например, если весь файл умещается в один MapView)

    GoldFinch
    Асинхронное чтение имеет смысл там, где обработка данных занимает время, сравнимое с их чтением с диска. А в данном случае речь идет о простом сканировании строки, которое с учетом скоростей современных камней, ОЗУ и HDD по крайней мере на порядок быстрее чтения данных с диска

    qqwe
    Про ммф и сфоп - это все басни
     
  13. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    MuForum
    Учти, что дело м.б. еще и в сильной фрагментации файлов. Поэтому прежде чем браться за переделку можешь провести тест скорости чтения с диска - проще всего создать MapViewOfFile на весь файл и затем пробежаться по нему, читая по одному int из каждрй 4К страницы. Для нормальных не сильно фрагментированных файлов должна получиться скорость порядка 50-80 Мб/сек (т.е.50 Мб должны читаться порядка или менее 1 сек)
     
  14. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    Прошу читать мои сообщения ВНИМАТЕЛЬНЕЕ!!!
    Мне необходимо в ручную передвигать каретку/маркер!

    # Вопрос: Какую функцию для передвижения каретки/маркера можно использовать совместно с функцией открытия файла CreateFile()?


    - То есть, на сколько я понял, то необходимо сделать фрагментацию локального диска на котором я работаю?
     
  15. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    Благодарю.
    - Не заметил сразу...
     
  16. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    если нужно быстро - то нет.
     
  17. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    leo
    сделал бенчик. подопытный файл на ~6 гиг и читатели на мапинге и ридфайл. тк проверка не первая и памяти хватает, то почти нет обращений к диску. мм - ~12с, fl - ~13c. это среднее по нескольким проверкам. щас по разу перегружу чтоб незакэшированый отбенчить
     
  18. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    хм.. хотя результаты скачут раза в 2-3, можно остановиться на
    fl = 42
    mm = 42.375
    странно, что ридфайл чаще меньшие цифры выдавал при чтении с диска, а при из кэша чаще большие
     
  19. MuForum

    MuForum Member

    Публикаций:
    0
    Регистрация:
    11 мар 2007
    Сообщения:
    109
    Ребята, в общем спасибо всем за помощь.
    - Последний вариант кода получился таков, что файл в 50 метров обрабатывается за 1/3 секунды =)
    - Теперь осталась проблема только с прорисовкой. (В компонент TMemo большее 100'000 строк прорисовываются около 30 секунд...)
    - Теперь необходимо придумать как быстро прорисовывать.


    P.S. -> В общем у меня теперь идея следующая.
    - Хранить все строки в vector<string>, а при прокруке скрола/колесика, как-то прорисовывать только то содержимое, которое нужно. (Что-то в этом духе)
    - Собственно ничего умнее пока придумать не смог, собственно как и реализовать это я пока не знаю =(
     
  20. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    рисуйте окна 3 с отображаемым по центру в компатибл битмап (а лучше в серию с шагом вашего скрола) и блитьте отображаемое в окно, дорисовывая в офф по мере сдвига. так можно очень гладко сделать даже на медленных компах. но врядли вам такое надо