парсинг файла: как быстрее?

Тема в разделе "LANGS.C", создана пользователем varnie, 20 янв 2009.

  1. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    прив~

    интересуют наибыстрейшие пути обработки данных, реализованные на плюсах (полагаю, с подгрузкой следующего блока данных по запросу). что-то близкое к работе парсера любого компилера/интерпретатора. т.е. исходный файл считывается в память не сразу, а последовательно, по кускам, парсится, если все ок, то запрашивается сл порция.
    кто сталкивалса с подобным? или же не заморачиваться, и целиком считать файл в std::vector<std::string> и работать с ним, без всяких подкачек?
    в инете нарыл какую-то простенькую схему "double buffer scheme", где используются 2 буффера, и по прочтению первого, переключаемся на второй, а первый подгружаем заново.
    вот и озадачилса, как все же поступить?

    приветствуются любые адекватные предложения. спасибо.
     
  2. varnie

    varnie New Member

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

    AndreyMust19 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    714
    Я думаю, что размер буфера лучше определяться по тому - как часто парсеру приходится менять алгоритм своей работы (если часто, то и буфер должен быть меньше). То есть - чем "проще" текст, чем большие порции надо читать. Хотя подожди, вот скоро сюда еще кто-то придет и напишет - что все это бред и предложит собственный вариант.

    Я не понимаю - зачем там два буфера и...
    это как? 2 потока что ли (один - заполняет буфер, а из другого читаются данные)? Поясни.

    По поводу использования неск. буферов есть только такая идея - можно иметь несколько буферов одинакового размера и читать / писать из них данные в одном цикле (счетчик цикла будет для всех буферов общим). Так мы только сэкономим на циклах (зато наверняка проиграем в объеме алгоритма).
    Это хорошая идея! Можно в одном цикле читать данные из 2-го буфера.
     
  4. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    лучше всего использовать кольцевой буфер разделенный на 3-4 сектора и работа в 2 потока. после распарсивания очередного сектора один из потоков устанавливает соответствующее событие, другой из потоков после считывания в очередной сектор устанавливает тоже соответствующее событие. Само собой перед переходом в очередной сектор ожидается снова соответствующее событие из другого потока. Так если секторов 4, событий - 8.

    АДД
    точку поставил
     
  5. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    varnie
    MemoryMappedFile(CreateFileMapping)
    Сам будет подгружаться по мере обращения.
     
  6. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    Partner
    проще, но не быстрее, тк читаться с диска начнется только после обращения, а сама читка - медленная операция
     
  7. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    меня интересует кросс-платформенный подход, чистый С++ (STL/Boost/etc). WinAPI не подходит..
     
  8. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    скажем, каким образом разные парсеры определяют для себя, как подгружать данные: сразу же целиком за раз, или же по кускам по мере процесса парсинга, или еще как...

    решение влоб -- считать всё за раз в std::vector<std::string> и не мучиться. но я хочу рассмотреть и другие подходы (полагаю, более грамотные).
     
  9. perez

    perez Member

    Публикаций:
    0
    Регистрация:
    25 апр 2005
    Сообщения:
    502
    Адрес:
    Moscow city
    varnie
    Как вариант использовать предложенный_basmp_-ом способ + OpenMP, который кроссплатформен и поддерживается многими компиляторами.
     
  10. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    varnie
    Зависит от размера входных данных. Считать за раз хорошая идея. Вот если тебе надо распаристь большой файл. Первый вопрос зачем это надо?
     
  11. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    varnie
    при достаточно длинных файлах, решение в лоб будет тормозить, тк вы сперва дождетесь полного считывания через 2 буфера, а потом еще и парсить будете
     
  12. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Pavia
    предположим, есть некая модель парсинга входных статистических данных. а входной файл с данными может быть от пары десятков байт по размеру до неск килобайт (теоретически).
     
  13. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    _basmp_
    под решением в лоб имелось ввиду полное единократное считывание данных в один буфер.

    решение же с использованием двухбуферную схему подразумевает под собою:
     
  14. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    varnie
    когда я говорил о полном чтении через 2 буфера имелось ввиду, что сперва полностью читается в кэш, а затем гонится в ваш буфер, а прога все это время ждет. Но если пару байт-пару килобайт, то без разницы
     
  15. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    STL наверное не лучший подход. Этот самый <vector> of <string>-s как раз может замедлить ухищрения с буферами. Если речь идёт о файлах в несколько килобайт - тогда файл целиком в память через malloc() и затем разбирать символ за символом. Если файлы больше, скажем двух мегабайт - тогда можно выбрать буфер подходящего размера - например 512 Кб с подкачкой.
     
  16. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    Вообще-то оптимальный метод чтения для однопоточной модели зависит от типа данных файла, т.к. парсер обрабатывает конкретные блоки кода, то и читаем блоками кода или кратно им.
    Тип файла Метод чтения
    Текстовые файлы Строками
    Базы данных Полями
    Двоичный (формат данных не знаем, Блоками, размером не меньшим, чем max
    но будем распознавать) размер формата данных
     
  17. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Vam
    благодарю за ответ.
    т.е. в моем случае выходит стОит читать файл по-строчно?
    так почему же выше идею о первоначальном считывании всего файла в std::vector<std::string> > забраковали? IMHO, в любом случае имеет смысл сразу же считать весь файл в буфер (контейнер).
     
  18. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    varnie
    ЛОЛ. При таких мизерных размерах вообще непонятно, откуда вопрос возник. Одно дело, если бы размеры файла гигабайтами - десятками гигабайт исчислялись, а тут всего несколько секторов в худшем случае. ИМХО однозначно всё сразу считывать.
     
  19. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    varnie
    "Идею о первоначальном считывании всего файла" никто не забраковывал, т.к. все дело в размере файла. При обычном буферированном чтении (без флага FILE_FLAG_NO_BUFERING) винда читает файлы в системный кэш страницами по 4К да еще с упреждением до 64К. Поэтому для файлов в несколько Кб остается только скопировать их целиком в свой буфер, чтобы минимизировать потери на лишние обращения к ядру (ReadFile).
    А построчное чтение это вообще "казуистика", + в данном случае еще и "антиоптимизация", т.к. для разбивки на строки CRT по любому сначала читает данные из сис.кэша в некий внутренний буфер, ищет в нем разделители строк и затем копирует символы в твой буфер строки - налицо куча ненужных промежуточных действий, которые можно совместить с парсингом
     
  20. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    leo
    спасибо за пост.
    но, я так и не увидел внятного ответа касаемо сабжа. (может, плохо понимаю размытые фразы).

    l_inc
    в том то и дело, что размер входных данных варьируется. теоретически может быть и неск. сотен килобайт.