| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Perl: Общие вопросы > вопрос по POE |
| Автор: DooZ 28.11.2006, 19:02 | ||
| вопрос есть пример:
все работает, все ок но если списко урлов будет скажем 10к и более скрипт ОЧЕНЬ-ОЧЕНЬ долго думает (функция _start думает) после чего вылетает с ошибкой типа: Can't locate Net/DNS/RR/A.pm in @INC (@INC contains: /usr/lib/perl5/site_perl/5.8.6/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.4/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.6 /usr/lib/perl5/site_perl/5.8.5 /usr/lib/perl5/site_perl/5.8.4 /usr/lib/perl5/site_perl/5.8.3 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.6/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.4/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.6 /usr/lib/perl5/vendor_perl/5.8.5 /usr/lib/perl5/vendor_perl/5.8.4 /usr/lib/perl5/vendor_perl/5.8.3 /usr/lib/perl5/vendor_perl /usr/lib/perl5/5.8.6/i386-linux-thread-multi /usr/lib/perl5/5.8.6 .) at (eval 64) line 3. что за бредятина? ставлю допустим 500 ссылок, все ок работает (подумаем чуток и работает) я понимаю, что он думает пока создает очередь запросов, но почему валится при большом кол-ве ссылок? есть идеи как сделать рабочим при большом кол-ве ссылок, может как-то дозированно выдавать ссылки (в рамках одного запуска) заранее сенькс |
| Автор: DooZ 29.11.2006, 17:57 |
| подозреваю что нужно как-то работать с $kernel->yield( $event, @event_args ); НО тогда не могу понять как перехватывать my ( $heap, $request_packet, $response_packet ) = @_[ HEAP, ARG0, ARG1 ]; вот эти два аргумента ARG0, ARG1 $_[ARG0] уже не пашет $_[0] тоже не пашет есть идеи? |
| Автор: DooZ 20.12.2006, 11:22 |
| неужели никто не работал с POE ? |
| Автор: Ramirez 20.12.2006, 13:47 |
| Похоже так. Я вот тут тоже задавал вопрос - и тишина |
| Автор: DooZ 22.12.2006, 11:22 | ||||||
ты попробуй поставить например 20.000 ссылок или поболее валится или нет? на 1000 ссылках быстро обработал (загнал к себе в память?) |
| Автор: nitr 23.12.2006, 19:11 | ||
Не валится (13778ссылок), но работает небыстро Выложи в инете список с большим количеством ссылок |
| Автор: nitr 23.12.2006, 19:33 | ||
проверил скрипт на
скрипт считает количество ссылок Скрипт с твоми кодом "не отвалился"! Код твой рабочий, но требует оптимизации, не надо провоцировать людей, конкретно спрашивать Да - он "загоняет" это всё в ОЗУ (281 504Кб) |
| Автор: DooZ 27.12.2006, 19:13 |
| видимо косяк в модулях действительно буду искать =) сенькс |
| Автор: DooZ 29.12.2006, 21:50 |
| возник новый вопрос: для начала сенькс всем кто учавствовал и учавствует в теме, разобрался дело было в модуле вот есть массив с большим кол-вом ссылок скажем 100к ссылок можно ли как-то сделать, что бы работало в цикле, а именно типа foreach my $url (@url) { POE::Session->create (inline_states => {_start => sub {$_[KERNEL]->post(ua => request => got_response => GET $url);}, got_response => \&client_handle_response}); } НО не как работает в данном варианте (ДОЛГО, ОЧЕНЬ ДОЛГО он думает потом начинает работу) а по мере поступления инфы тобишь получил первую ссылку и погнал ее обрабатывать, в том время как дальше по циклу наполняются остальные т.е. сразу по мере получения начал отрабатывать заранее сенькс |
| Автор: DooZ 2.1.2007, 19:20 |
| есть идеи? |
| Автор: DooZ 22.1.2007, 11:20 |
| ап |
| Автор: Ramirez 7.2.2007, 13:31 |
| так ты @url из файла наверное наполняешь? так не гони все это в память. в цикле чтения и запускай обработчиков. |
| Автор: Nab 1.3.2007, 05:56 |
| Ну что разобрался? Или так и пытаешься все в цикле сделать? Просто я вот решил изучить POE переписывая свой проксичекер с форков на POE, и выяснил много интересного. А так как строил на тех же примерах, что и у тебя используются, могу подсказать где косяк у тебя У меня другая немного проблема, потому как я всеже не по ссылкам лажу, хотя это тоже предстоит, я проверяю один адрес, но через разные прокси, соответственно большую нагрузку могу создать, поэтому ограничиваю свой поток запросов. Но все одно, через некоторое время стабильно 500 ошибка |
| Автор: tishaishii 2.3.2007, 21:06 |
| А шо воно такоэ? |
| Автор: Nab 2.3.2007, 23:47 |
О чем именно ты справшиваешь? Если о POE, то по любому сначала вот сюда http://poe.perl.org/. А вообщето это фраймворк реализующий невытесняющую многозадачность основанную на событийной модели. Очень хорош для всяких демонов, серверов, конечных автоматов и многого другого... |
| Автор: tishaishii 3.3.2007, 18:17 |
| Понятно, ещё одна примочка для разработки. Ну это не новость. |
| Автор: shamber 3.3.2007, 20:06 |
| tishaishii, примочка и еще какая!!! Очень удобно работать. |
| Автор: tishaishii 3.3.2007, 20:16 |
| Мне удобно создать свой интерфейсный класс, от него родить нужные мне классы и написать что мне надо. |
| Автор: Nab 3.3.2007, 21:51 | ||
Интересно сколько времени на это у тебя уйдет |
| Автор: shamber 3.3.2007, 23:54 |
| Особенно на нечто подобное POE |
| Автор: DooZ 9.3.2007, 12:01 | ||
был бы благодарен за пример =) |
| Автор: Nab 11.3.2007, 00:32 | ||||||
Ок, объясню на твоем же примере ...
Если внимательно вчитаться в описание POE то там достаточно четко говориться что это такое и зачем, а именно Фраймворк управляемый событиями с невытесняющей многозадачностью... А теперь объясню подробнее. Понятие невытесняющей исходит из того, что POE в изначальном варианте выполняется одним процессом и разделение времени выполнения между разными сессиями происходит внутри одного единственного процесса. А означает это то, POE само по себе, не может переключиться на другую задачу(сессию) для выполнения поставленной задачи или реагирования на событие... Необходимо отдавать управление POE из своей процедуры, в особенности если она заведомо продолжительна во времени... Следующее, сессия в POE в терминах операционнки, это как отдельный процесс. Посему создание сессии для каждого запроса это нонсенс :( думаю просто непонимание того как работает эта система, и невнимательное списывание с примеров... нигде такого даже не встречал :( В цикле нужно посылать сообщения к определенной сессии, не более... И желательно давать возможность хоть иногда их отработать Способов передать управление есть несколько, это и run_one_timeslice, и всякого рода таймауты, но самый простой это просто смена цикла на посылку сообщений самому себе... Вот один из примеров как можно вызвать загрузку твоих урлов и начать получать ответы задолго до окончания списка...
Для уменьшения нагрузки на CPU я применяю для таких достаточно длинных запросов такой запрос $_[KERNEL]->delay('send_request', 1) нагрузка с 70-80% падает до 1% правда и время выполнения увеличивается вдвое, но все зависит от поставленной задачи, и приемлимой скорости проверки урлов... Также временной промежуток можно другой поставить... А вообще, я еще несколько решений у себя попробовал в процессе разделения задачи на части. И как результат, была написана парочка компонентов и один фильтр |
| Автор: tishaishii 11.3.2007, 01:41 | ||
В таких модулях, как правило, куча хлама - на все случаи жизни, который, как правило, в одном проекте весь не используюется. Так что не много времени, зато как надо. |
| Автор: Nab 11.3.2007, 07:28 | ||
Ну если следовать такой логике, то врядли все возможности перла используются в каждом проекте, может напишешь свою, облегченную версию? Естественно некоторая избыточность присутствует, но обыкновенно в таких системах только необходимый функционал, а весь дополнительный вынесен во внешние компоненты, плагины и т.д. так что собирать нужный конструктор весьма недолго... Зато получается, весьма расширяемая, хорошо сопровождаемая, и быстро написанная система... Естественно я не говорю о самодостаточных скриптах, которые раз написал и забыл... |
| Автор: tishaishii 11.3.2007, 12:00 |
| Вобщем, существует две концепции: использовать готовый код и писать свой. Это такая диалектика кодинга. Думаю, истина где-то по-середине, как обычно. |
| Автор: G0rinich 30.3.2007, 13:13 | ||||
| Nab, а не боишься такими темпами свалить процесс? Да, POE::Component::Client::HTTP способен делать параллельно несколько запросов. Но отдать ему сразу 100К запросов - напряг А если запросов надо сделать миллионы? Во первых ссылки надо хранить в БД и брать их оттуда пачками. Вот пример
Ну и код драйвера:
Код гарантированно рабочий. Хавает ~10 линков в секунду. Одновременно обрабатывает не более $JOBSMAX ссылок. |
| Автор: Nab 30.3.2007, 19:23 |
| G0rinich, молодец однако И все верно говоришь, можно запросто завалить не только весь проект Хотелось немного проще показать как оно работает, чтобы сразу не отжирать кучу ресурсов и не создавать ненужные сессии стрвктуры, и т.д. Согласен, что с этими тонкостями человек столкнеся на следующем этапе, но они не принципиальны по сравнению к примеру со старым кодом |
| Автор: G0rinich 1.4.2007, 09:07 |
| Айс? |
| Автор: Ramirez 1.4.2007, 19:22 |
| Интересный топик. Я тоже уже пару месяцев с POE разбираюсь, вопросов много появляется, а документации нехватает, чесно говоря. Та что на poe.perl.org - частично устарела, особенно статьи. Может стоит отдельный подраздел на форуме завести? |
| Автор: nitr 1.4.2007, 20:28 |
| Ramirez, отличное предложение Добавлено через 36 секунд я имел те, что вынесли как подфорум или подраздел... |
| Автор: shamber 1.4.2007, 20:44 |
| Я тоже поддерживаю данное предложение. Потому как, мне кажется, уже много людей на этом форуме пытаются с poe работать. Это позволило бы обощить опыт |
| Автор: Ramirez 1.4.2007, 23:02 | ||
Может попробовать перевести совместно документацию? И дополнить ее своими примерами/опытом.. Если, конечно, желающие есть? Можно было-бы завести Wiki например...
Если я правильно понимаю, то POE в данном случае выполняет роль диспетчера процессов. В вытесняющей многозадачности диспетчер может сам снять процесс по истечении отведенного ему времени. В невытесняющей модели, диспетчер процессов сам не может этого сделать, поэтому процессы сами должны возвращать ему управление как можно чаще, а он только собирает очередь и решает какой процесс вызвать следующим. Практически, это сводится к тому, что мы должны свести к минимуму использование циклов внутри процессов, а все циклы разбить на последовательные вызовы. Да и вообще, почти все вызовы делать через ядро POE. Поправьте меня, если я что-то путаю... |
| Автор: Nab 2.4.2007, 13:15 | ||
Вот именно.... Очень хорошо поняли и изложили |
| Автор: G0rinich 4.4.2007, 15:45 |
| Самое зло - это использовать sleep в POE ))) |
| Автор: stan777 4.4.2007, 23:35 | ||
А что быстрей РОЕ, форки или треды ? ну все естественно на Unix, я так понимаю алгорит паука вездет тотже без цикла типа for(@url){..} ? |
| Автор: Nab 5.4.2007, 01:00 | ||
А эт зависит от того что иммется ввиду по словом "быстрее" Быстрее написать на POE если его конечно знаешь... А вот работает у меня быстрее всего на форках, хотя треды я еще не пробовал, но говорят под никсами, они реализованы не лучшим образом :( Добавлено через 5 минут и 44 секунды Но я пока POE знаю не очень, но всеже склоняюсь именно к нему, и на нем буду делать все, на форках сложнее, особенно межпроцесовое общение... А POE хорош тем что имеет компонентную архитектуру, и если делать все по правилам, то наращивать функционал будет много проще... |
| Автор: G0rinich 5.4.2007, 07:44 |
| POE сам умеет форкаться когда надо. Вернее в нем есть какой-то механизм форков, но я всегда наблюдал только один процесс. От форков я отказался. Вернее от того, что там в перле под именем FORK живет. Так как вообще не понял как оно работает ))) Слабоват я тогда был в никсах, а теперь не кайф про это вспоминать ))) Уж лучше руками запустить несколько раз один скрипт, предварительно научив копии не мешать друг другу. |
| Автор: Ramirez 5.4.2007, 09:17 | ||
| я тут пробовал POE::Component::EasyDBI неблокирующий доступ к базе реализует, так вот он висит отдельным процессом в системе... Вот, кстати есть такой вопрос. Вот код для примера:
при подключении клиента, в процедуре client_connect ставится задержка 5 секунд, по истечении которых сессия закрывается. в процедуре client_input проверяем ввод клиента, и например, если введено слово "auth" отменяем запланированное закрытие сессии. Так вот бывают ситуации, коннект плохой например, когда в очередь уже встали другие события для этой сессии (через yield), но перед ними стоит событие shutdown, оно естественно происходит, закрывает сессию, а потом приходят следующие события, сессии такой уже нет, и скрипт вываливается :( Мне казалось что POE должен сам такие ситуации корректно обрабатывать. Видимо где-то я логику не улавливаю... |
| Автор: shamber 5.4.2007, 11:22 |
| Так ты же сделай просто $heap->flag. проверяй его и если он не выставлен например, то функция отрабатывает, а если выставлен то выход. Я так подобные систуации разруливал |
| Автор: stan777 5.4.2007, 18:01 | ||||
Я так понял что тут обсуждается таже проблема велосипеда, то есть паука. Да на форках я тоже хочу написать, вот только как разберусь с IPC::Shareable, мне кажется это быстрей чем через pipe()'ы, хотя риализации, ни на расшареной памяти ни на пайпах у меня нет, хотя вот на тредах работает вроде нормально, это лучший вариант который я имею на сегодняшний день, хотя жрет много памяти 70 тредов 250 мегов, это на FreeBSD 6.1. |
| Автор: Ramirez 16.4.2007, 04:22 | ||||||
Нашел кажется
тогда, включится куча проверок (как написано в мане) и в том числе:
Вроде помогло.... |
| Автор: nagual2 16.6.2009, 07:50 |
| Прошло 2 года а пациент все там же ... Кто то решил данную проблему? |
| Автор: Ramirez 16.6.2009, 08:59 |
| Какую именно? G0rinich привел в треде наиболее академичный пример решения проблемы. Nab - наиболее простой для понимания, но с некоторыми нюансами. |
| Автор: nagual2 17.6.2009, 11:32 | ||||
А как приведенные варианты будут работать с
|
| Автор: nagual2 17.6.2009, 11:50 | ||
| Паука я уже сделал ... там еще патчик есть на poe http://groups.google.com/group/perl.poe/browse_thread/thread/8b1375f86d515914/12f9263fef5314ea?hl=en%0Cf9263fef5314ea Еще я хотел fcgi приложение написать на poe но там другая проблема http://forum.sysfaq.ru/index.php?showtopic=21878&pid=385670&st=0&#entry385670 Я писал разработчику
Но его код из гиты тоже нерабочий Добавлено через 4 минуты и 13 секунд Кстати как зствать poe нагружать все головы проца а не одну ? |
| Автор: Ramirez 17.6.2009, 16:36 |
| POE всегда испоняется в одном процессе. Можно использовать POE::Wheel::Run для запуска чего-либо отдельным подпроцессом. Тогда эти процессы смогут работать на разных ядрах. При этом с созданным процессом сохряняется связь через stdin, stdout, stderr. так например POE::Component::EasyDBI работает. |
| Автор: nagual2 17.7.2009, 15:39 | ||
А как переделать для многопоточности такое:
Куда встроить цикл ? Кстати в use POE qw(Component::Client::Whois); я встроил а в этот незнаю ... пока ... |