| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Программирование под Unix/Linux > Большой бинарный файл (2Гб) |
| Автор: Fabio 12.9.2011, 21:38 |
| Всех приветствую. Суть вопроса: есть дампы сетевого трафика (типа netflow), которые генерятся биллингом UTM5, у меня они по 2Гб. Их формат известен. Поставил себе задачу рисовать графики потребления трафика в личном кабинете абонента - за час, за сутки и за месяц. Соль в том, что при тупом последовательном чтении бинарной структуры из этого файла будет затрачиваться слишком много времени. Как можно ускорить данную процедуру? Примеры кода не обязательно, хотя бы ссылки на алгоритмы подобных операций, теоретические размышления, всё сгодится! PS Код ещё не писал, да и вообще под никсами пока не кодил, но не в этом суть. Я хочу сделать на C программулину, что-то типа посредника, которая будет быстро искать данные в этих файлах, основываясь на id лицевого счёта абонента и временного диапазона, интерполировать их под временные оси графиков и отдавать, например, через stdout, подготовленные данные вызывающему её php-сценарию. |
| Автор: newbee 12.9.2011, 21:47 |
| mmap для отображения файла в память, кеш для однажды отрендеренных графиков. |
| Автор: Fabio 12.9.2011, 22:25 |
| Немного осложняется тем, что на сервере всего 2 Гб оперативки и занято в среднем 1,3 Гб + своп на 1Гб и в нём со временем становится занято 300 Мбайт непонятно чего. Так что проецировать придётся не весь файл, а где-то по 100Мбайт. Кэш не катит, т.к. графики рисуются от текущего момента - это обязательное условие моего ТЗ. Скорее нужно будет придумать механизм защиты от DDoS-а юзеров, особенно тех, которые будут в браузере долбасить F5. Думаю предусмотреть в программе что-нибудь вроде мьютекса (можно даже семафор, если допустить возможность параллельной работы нескольких программ) и если он занят, то программка будет завершать свою работу, возвращая сценарию код ошибки, а сценарий в свою очередь скажет юзеру, типа "система занята, повторите запрос позже". |
| Автор: maxim1000 12.9.2011, 22:30 |
| предобработка, которая уменьшит количество информации т.е. каждый день считаем набор чисел, соответствующий данным, по которым строятся графики по идее, их должно быть гораздо меньше при запросе клиента используем эти данные для большей конкретики нужно знать, какие даные и как часто они меняются... |
| Автор: Fabio 12.9.2011, 22:40 | ||
| maxim1000, не непрокатит, т.к. данные в файле - последовательность структур определённого размера (никогда не меняющегося), в каждой структуре поля различных числовых типов. У файла отсутствует заголовок, т.е. тупо raw бинарник. А уже по этим полям и надо производить поиск данных - фильтрацию. Проблемка в том, что временные метки ставятся не через определённый промежуток, а как "попало" (набежало в коллектор N байт, биллинг сделал штамп и отправил на запись в файл - это очень условно, по правде там буфера, что-бы винт не мучать). Этот момент и не позволит подготавливать каким-либо образом эти данные. Грубо говоря они уже подготовлены ))) UPD Формат привожу с форума биллинга
Как будет быстрее работать? - сначала выбрать в память все структуры с нужным account_id и уже в них отбирать по времени или учитывать сразу все условия при обходе спроецированного участка? |
| Автор: Fabio 12.9.2011, 22:56 | ||||
Нашёл структуру, выдернута из одной сервисной OpenSource утилитки стороннего разработчика.
|
| Автор: Fabio 13.9.2011, 10:59 | ||
|
| Автор: shara 13.9.2011, 12:05 | ||
| Fabio, так храните два файла. Один с полной версией всей "хистори" и Второй, который будет содержать только ту инфу, что нужна для отчета. Всяко с маленьким файлом удобней работать. З.Ы. Магический алгоритм Еего все равно прийдется либо индексировать как-то, либо разбивать на части.. либо... в общем насколько у вас фантазии хватит. З.З.Ы. Так что скажете насчет
|
| Автор: Fabio 13.9.2011, 12:18 | ||
На счёт двух копий - нет смысла, там же ужимать нечего! Да и реализовать это не представляется возможным. В биллинге есть событие ротации этого лога трафика, можно по нему перегонять данные (не учитывая лишние поля в структуре, но всё равно придётся перегонять ВСЁ), но тут мы получим ... а ничего не получим, нахрен пользователю/админу смотреть данные на 1,5 - 3-е суток назад, когда нужно посмотреть сейчас Нужен интерактив. |
| Автор: fish9370 13.9.2011, 14:20 |
| то о чем вы здесь говорите называется агрегацией, да в любом случае агрегация приводит к усреднению значений, т.е. нельзя точно сказать что происходило в какой-то конкретный момент времени.. но это весьма полезно поскольку, объем трафика огромен, и делать поиск по 2гб не разумно долго.. файл UTM вероятнее всего открывает в режиме "a", т.е. для записи в конец, а это значит, что его можно открыть другим процессом и в реальном времени производить агрегацию, т.е. суммировать трафик и усреднять значение, записывая в новый файл.. насчет эффективности, полагаю этот метод вполне себе эфективен, т.к. врядли UTM делает после каждого цикла записи flush, чем сбрасывает грязные буферы.. вообще вопрос агрегации, для биллингов не нов, все так или иначе умеют это делать, может стоит порыться в настройках UTM? так же хочу напомнить, что помимо нетфлоу, можно считать трафик по апдейтам радиуса, это тоже общепринятый метод.. но там скорее всего без агрегации тоже не обойтись.. |
| Автор: Fabio 13.9.2011, 14:33 | ||||
Добавлено @ 14:42 Самой хорошей на данный момент идеей является поднятие ещё одного стороннего коллктора, например, nfdump. Ограничить объём логов трафика до 30 суток (что-бы место на ХДД не расходовал). Сенсором трафика у меня является модуль iptables ipt_NETFLOW, он позволит отсылать данные двум коллекторам: биллингу и nfdump. Для nfdump существует perl визуализатор nfsen. Но опять-же - это всё рубит на корню идею с графиками в личных кабинетах, т.к. теряется связь между account_id и непосредственно трафиком. IP адреса в нашей сети динамические. PS Да, и этим размышлениям не место в программистском форуме, последний абзац лучше смотрелся-бы на наге... |
| Автор: bsa 13.9.2011, 18:19 |
| Fabio, думаю стоит возвратиться обратно к "тупой обработке файла". Итак: 1. файл бинарный 2. файл содержит N=2GB/sizeof(DataStruct) записей 3. размер записи фиксированный Что делаем: 1. открываем файл, ммапим в ОЗУ (эта операция не тербует от тебя наличия такого количества свободной памяти - ОС сама прозрачно будет подгружать нужные части, главное, чтобы размер области был кратен размеру страницы памяти, обычно, 4096 байт) и читаем первую и последнюю метку времени, если необходимое нам время не лежит где-то между ними, то открываем предыдущий/следующий файл 2. необходимая метка лежит где-то между первой и последней, выбираем примерный номер подходящей нам записи на основании ее смещения относительно начала (i = (end - beg)/(met - beg)) 3. используем полученный номер как первую итерацию в бинарном поиске метки близкой к искомой (т.е. совсем не обязательно, что ты найдешь то что хотел, но с отклонением в несколько сек - запросто) 4. начинаешь последовательный перебор записей по полю account_id до конца файла, информацию из подходящих записей выводишь в stdout. P.S.: логично использовать для доступа к отображенной области типизированный указатель на const DataStruct |
| Автор: Fabio 13.9.2011, 18:48 |
| bsa, большое спасибо! Истина где то рядом (с). UPD Ооох чую жесть будет, когда начну пробовать, тамже придётся осваивать gdb, а без отладки никуда... Сервак-то консольный, с доступом только по ssh |
| Автор: newbee 13.9.2011, 21:56 |
| Fabio, настоящие мужчины знают, что пишут, и не пользуются отладчиками! Попробуй, и ты сможешь. Добавлено через 40 секунд Я вот сколько под линуксы ни писала, ни разу gdb не запускала |
| Автор: Fabio 13.9.2011, 21:59 |
| newbee, жаль плюсануть пока не могу |
| Автор: Fabio 13.9.2011, 23:08 |
| Так, оказывается ещё надо учитывать то, что файл нужно обрабатывать с конца, т.к. там самые новые данные. А то я сначала загнался, что в момент обработки файла моей программой есть вероятность сброса биллингом новой порции данных, но т.к. новые данные дописываются в конец файла, то в принципе ни чего страшного не должно произойти. Главное, что-бы указатели в памяти не менялись. |
| Автор: bsa 14.9.2011, 17:35 | ||
Скопируй на свой комп файл статистики и отлаживай свою прогу под любимой IDE. |
| Автор: Fabio 14.9.2011, 17:43 |
| |
| Автор: gcc 17.9.2011, 00:21 | ||||
| бинарный поиск ? Добавлено через 10 минут и 2 секунды
http://search.cpan.org/~jfreeman/File-SortedSeek-0.015/lib/File/SortedSeek.pm File::SortedSeek |