MapViewOfFile or ReadFile

Тема в разделе "WASM.WIN32", создана пользователем Mezonin, 29 окт 2004.

  1. Mezonin

    Mezonin New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2004
    Сообщения:
    12
    Адрес:
    Russia
    доброго времени суток, очень бы хотелось узнать: пробегая по дереву каталогов рекурсией, что лучше использовать для работы с файлами, мэппинг или непосредственное использование функций readfile&writefile, и почему ?
     
  2. Foamplast

    Foamplast New Member

    Публикаций:
    0
    Регистрация:
    6 ноя 2003
    Сообщения:
    80
    Адрес:
    Russia
    Ну, вроде в ядре есть только отображение. То есть при вызове CreateFile(..., GENERIC_READ... ) происходит отображение файла в память ядра. И ReadFile() просто копирует оттуда данные. Так что теоретически это всё равно.



    Практически:



    1. Иногда отображение удобнее использовать.

    2. Если отображать большой файл (700 Мб), то будет очень тормозно (у меня так). А если отображать его поочерёдно порциями по 100 Кб, то не будет никакой разницы между отображением и обычным чтением. В последнем случае ReadFile() даже проще.
     
  3. PavPS

    PavPS New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2004
    Сообщения:
    109
    Адрес:
    Russia
    По поводу отображения дольшого файла, то тормозить не будет всё равно. Кэш менеджер и так в память всё не возьмет. И вообще все эти отображения гениально продуманы в плане удобства и оптимизации. А по поводу ReadFile() - то да это проще, но вот и менно, что при ReadFile() копируются данные в буфер, а MapViewOfFile просто настраивает виртуальные адреса на блок, где на самом деле спроецирован файл. Тем более при вызове MapViewOfFile подпроцедур вызывается меньше, чем при ReadFile().
     
  4. Mezonin

    Mezonin New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2004
    Сообщения:
    12
    Адрес:
    Russia
    Тогда возникает вопрос: до CreateFile механизм в принципе одинаков для обоих способов, а различия начинаются уже после ?
     
  5. Mezonin

    Mezonin New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2004
    Сообщения:
    12
    Адрес:
    Russia
    И еще хотелось бы узнать, что на происходит при выхове CreateFileMapping.
     
  6. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    > И еще хотелось бы узнать, что на происходит при выхове CreateFileMapping.



    The CreateFileMapping function creates a named or unnamed file-mapping object for the specified file.

    Return Values

    If the function succeeds, the return value is a handle to the file-mapping object.
     
  7. Mezonin

    Mezonin New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2004
    Сообщения:
    12
    Адрес:
    Russia
    Я понимаю, MSDN и у меня есть, меня интересует внутренний механизм работы, если вопрос этот неуместен здесь, то хотя бы где искать описание.
     
  8. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Описание поискать в IDA. Дизассемблируются три файла - kernel32.dll/ntdll.dll/ntoskrnl.exe. И вопрос уходит.
     
  9. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    PavPS







    Если ReadFile копирует в буфер, то я так понял, что это хранится в ОЗУ, а при MapViewOfFile сами данные где хранятся, т.е. куда спроецирован файл, и откуда читаются данные? Судя по распределению памяти, при MapViewOfFile в оперативную память они не загружаются, например MapViewOfFile для файла 30-40 Мб никак не увеличивает выделение памяти. Получается они (данные) так и остались на винте. Если так, то не получится для файлов такого размера, что с ReadFile будет гораздо быстрее доступ к данным, хранящимся в оперативной памяти, чем с MapViewOfFile, если в последнем случае данные приходится доставать с винта?
     
  10. Foamplast

    Foamplast New Member

    Публикаций:
    0
    Регистрация:
    6 ноя 2003
    Сообщения:
    80
    Адрес:
    Russia
    Блин, объснял же:



    При открытии файла его чать проецируется на область памяти ядра. ReadFile() именно оттуда и читает, а MapViewOfFile() настраивает адреса так, что при чтении-записи страниц памяти, на которые спроецирован файл, происходит либо чтение из кэша, либо подкачка с диска.



    Так что всё одно, если не считать того, что ReadFile() тратит время на пересылку данных в буфер пользователя.
     
  11. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Foamplast

    ReadFile() тратит время на пересылку данных в буфер пользователя

    Afaik если файл открыт с использованием FILE_FLAG_NO_BUFFERING, то этого не происходит.
     
  12. PavPS

    PavPS New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2004
    Сообщения:
    109
    Адрес:
    Russia
    Вообще, тема это большая и сложная, как мне кажется. Больше всего ответов, действительно из IDA + SoftIce. Так же не обойтись без David A. Solomon and Mark E. Russinovich с их гнигой InWin2k.

    Вопрос файловых отображений и дисковых IO ессно затрагивает Cache Manager-а.

    Все чтения с диска идут через IoPageRead. Эта функция и получает живенькие байтики с винта/диска. Ну вообще, если быть точнее, то облагораживает данные и посылает к девайсу нужного устройства. Соответствующие драйвера связываются с CcCopyRead, которая окончательно находит девайс, соответственный за это устройство и читает уже данные. Данные попадают в кэш, строение которого замечательно описано у Соломона. Причем, чё я заметил, то что они всегда попают в кэш сначалаТак вот, если вазвано чтение было через ReadFile, то потом из кэша данные попадают в Твой буфер (rep movsd). Если же это MavPiewOfFile, то адреса виртуальные настраиваются на кэш, а он ессно ограничен в своих размерах. Ну да ладно, итак, вазвав MavPiewOfFile для 40 метрового файла в КЭШе и памяти будет только часть, а остальные адреса, соответствеющие большим смещениям в файле поначалу будет инвалидными. При попытке прочитать их будет вызван PageFault, который просит разобраться во всём ф-ю IoPageRead, и страничка подгружается… вот в принципе и всё..

    По поводу быстродействия – это всё таки MavPiewOfFile. Причем, всего лишь при первом обращении к файлу, он уже кэшируется. Пусть Ты даже размер только его проверял. (на моей практике так было)

    Так же из практики выяснил, что любой файл пишется ч/з ф-ю CcWrite.



    P.S. Очень буду рад побеседовать на эту тему. Самому очень интересно, да и работа простаивает из-за этой темноты…
     
  13. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    PavPS



    Я тут маленький эксперимент сделал по поводу MapViewOfFile vs ReadFile, суть такова:



    Первый эксперимент:

    1. CreateFile > CreateFileMapping > MapViewOfFile

    2. Выполнение действий с этим "отображением" по всему объёму файла.



    Второй эксперимент:

    1. CreateFile > GlobalAlloc > GlobalLock > ReadFile

    2. Выполнение действий со всем объёмом, считанным в ОЗУ



    Для MapViewOfFile я очень быстро получаю доступ к объекту обработки (содержимому файла), но работается с ним очень медленно, ReadFile же наоборот, заставляет ждать полной загрузки, но затем обработка данных происходит быстро. Для "выполняемых действий" выбрал процедуру сортировки, т.к. она одновременно работает со всем объёмом. Результаты примерно такие (цифры ни о чем не скажут, но пропорции верные)

    MapViewOfFile - получение отображения и готовность к действиям - 15-30 мс, обработка данных - 2000-3000 мс

    ReadFile - получение данных и готовность к обработке - 2000-2500 мс, обработка данных - 140-150 мс. Процедура обработки одна и та же.

    Можно ли как-нибудь совместить достоинства обоих способов: быстроту готовности к обработке MapViewOfFile и скорость обработки за счёт того, что все данные в озу (ReadFile)? Или это невозможно?
     
  14. PavPS

    PavPS New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2004
    Сообщения:
    109
    Адрес:
    Russia
    Ну вообще, я тоже эксперементировал. Ну возьми файл 200 метров и открой его для просмотра (totalcommander::F3)прокрути вниз/верх и так много раз. Сначала будет тормозить а потом даже и к винту обращаться не будет. А результат Твой, впрочем, ожидаемый.

    А чё ты хотел, у MapViewOfFile куча приемуществ, что не так уж и заметны Твои недостатки в скорости. А вообще странно. Поидее, после первого прохода по всему объему данных, последующие проходы должны быть без тормозов. А вообще стоит тут посмотреть на зависимость скорости от NonePaged/Paged memory pools.
     
  15. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    >




    IMHO этот PageFault и тормозит.

    Я тоже делал небольшие эксперименты и результаты похожие как у cresta.

    Пришёл к такому выводу: если нужно обработать файл целиком, то быстрее будет ReadFile.

    Если же нужны только какие-то части файла, и/или доступ к ним происходит "время от времени", тогда лучше MapViewOfFile.

    Короче, что лучше от задачи больше зависит.
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257




    Не знаю, кто такой PageFault, но из наблюдений за винтом при MapViewOfFile: при обработке данных винт крутится на полную катушку. Т.е. тормозит то, что данные берутся непосредственно с винта. Причём данные остаются в озу: в начале обработки под процесс выделено 1 Мб, к концу обработки выделение для процесса составляет 27-28 Мб. Получается, MapViewOfFile имеет преимущества, когда нельзя считать файл целиком, а при объёмах памяти, которые винда может выделить без особого напряга, с ReadFile быстрее. Или в случае работы с маленьким куском большого файла. Хотя где-то читал, что MapViewOfFile следует использовать где только можно :dntknw: