Самый добрый бегемот
С нами с 24.06.03
Сообщения: 954
Рейтинг: 574
|
Добавлено: 10/01/12 в 08:11 |
Надо написать программку на С++, которая в параметрах запуска примет N-urlов, ПАРАЛЛЕЛЬНО их скачает, а контент каждого положит в файл с заданным именем и путем. Сейчас задача решается путем параллельного запуска N-wgetов, что очень плохо сказывается на произодительности.
Кто может сделать, пишите в аську 523709. Обсудим бюджет =)
P.S. должно компилиться и работать на x86 и x86_64. Все под линукс.
|
|
|
|
С нами с 24.10.04
Сообщения: 18881
Рейтинг: 9010
|
Добавлено: 10/01/12 в 09:57 |
Оффтопик:
уверен, что по скорости и расходу ресурсов рнр+curl не уступает самопальному скрипту на с++
ну вот попробуй такая скорость устроит:
Код: [развернуть] |
<?
//ini_set('memory_limit', '512M');
//@ignore_user_abort(true);
//@set_time_limit(90);
$starttime = 0;
$starttime = explode(' ', microtime());
$starttime = $starttime[0] + $starttime[1];
$urls = array(
'http://translate.google.com/',
'http://slovari.yandex.ru/',
'http://dic.academic.ru/',
'http://www.translate.ru/',
'http://www.multitran.ru/',
'http://www.lingvo.ru/',
'http://psi.webzone.ru/',
'http://www.glossary.ru/',
'http://ru.wiktionary.org/',
'http://mirslovarei.com/'
);
echo '<xmp>'.print_r($urls,1).'</xmp>';
$contents = multi_get_url($urls);
foreach($contents as $i=>$content){
file_put_contents(dirname(__FILE__).'/tmp/'.$i.'.txt', $content);
}
function multi_get_url($urls){
global $headers,$cookie_file,$ua_list;
$mh = curl_multi_init();
$ua_list = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.24) Gecko/20111103 Firefox/3.6.24 sputnik 2.4.0.49';
foreach($urls as $i => $url){
$conn[$i]=curl_init($url);
curl_setopt($conn[$i], CURLOPT_POST, 0);
curl_setopt($conn[$i], CURLOPT_HEADER, 1);
curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1);
curl_setopt($conn[$i], CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($conn[$i], CURLOPT_MAXREDIRS, 0);
curl_setopt($conn[$i], CURLOPT_TIMEOUT, 60);
curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($conn[$i], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_multi_add_handle ($mh,$conn[$i]);
}
do{ $n=curl_multi_exec($mh,$active); } while ($active);
foreach($urls as $i => $url) {
$content[$i]=curl_multi_getcontent($conn[$i]);
if(isset($content[$i]))$aCURLinfo[$i] = curl_getInfo($conn[$i]);
curl_multi_remove_handle($mh,$conn[$i]);
curl_close($conn[$i]);
}
curl_multi_close($mh);
return $content;
}
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$gentime = round(($endtime - $starttime), 4);
echo "<br>time: ".$gentime;
exit;
?>
|
|
|
|
|
С нами с 25.07.06
Сообщения: 207
Рейтинг: 229
|
Добавлено: 10/01/12 в 10:04 |
на c++ будет дорого и трудноподдерживаемо. рекомендую python multi-threading. фактически, та же асинхронная загрузка, но будет работать везде
что-то такое, накидал за 5 минут :
Код: | #!/usr/bin/env python
# -*- coding: utf-8 -*-
import urllib2
import sys
from threading import Thread
class Downloader(Thread):
def __init__(self, url):
Thread.__init__(self)
self.url = url
self.out_file = url.split('/')[-1]
def run(self):
print '>', self.url, 'starting'
f = open(self.out_file, 'wb', 8096)
u = urllib2.urlopen(self.url)
data = u.read(8096)
size = 0
while data:
f.write(data)
size += len(data)
print '>', self.url, size, 'bytes'
data = u.read(8096)
f.close()
print '>', self.url, 'received', size, 'bytes'
if __name__ == '__main__':
if len(sys.argv) != 2:
print 'Use %s urllist.txt' % sys.argv[0]
sys.exit(1)
pool = []
for l in open(sys.argv[1]).readlines():
l = l.strip()
t = Downloader(l)
pool.append(t)
t.start()
print 'Waiting threads'
for t in pool:
t.join()
|
запуск - python downloader.py ulist.txt,
в ulist - список урлов по одному на строку. следи, чтобы имена файлов в урлах не повторялись для текущего каталога.
|
|
|
|
Самый добрый бегемот
С нами с 24.06.03
Сообщения: 954
Рейтинг: 574
|
Добавлено: 10/01/12 в 10:18 |
Всем поставил рейтинга по максимуму
Спасибо
Ушел тестить
|
|
|
|
С нами с 18.08.04
Сообщения: 6376
Рейтинг: 4430
|
Добавлено: 10/01/12 в 11:28 |
Salvator писал: | на c++ будет дорого и трудноподдерживаемо. рекомендую python multi-threading. фактически, та же асинхронная загрузка, но будет работать везде
|
Присоединяюсь. Отлично справляется питончик можно еще для гибкости прикрутить pycurl
|
|
|
|
Самый добрый бегемот
С нами с 24.06.03
Сообщения: 954
Рейтинг: 574
|
Добавлено: 10/01/12 в 11:29 |
Протестировали оба решения.
Текущий способ с запуском нескольких копий wget работает на порядки быстрее.
Не устраивает в текущей схеме то, что при достаточно большой нагрузке сервер складывается тупо от большого кол-ва запущенных процессов, т.е. судя по ТОПу task около 6к, при этом idle около 20%, I|O wait - не более 2%, а время тратится именно на переключение между задачами =( Вот собственно отсюда и растет необходимость в запуске 1 процесса, который параллельно дернет несколько урлов.
|
|
|
|
С нами с 08.02.03
Сообщения: 10564
Рейтинг: 5962
|
Добавлено: 10/01/12 в 13:31 |
atrius: а винты у тя там какие и паралельно это скока (количество и какую полосу по mrtg грузят)?
И кусок топа покаж
|
|
|
|
С нами с 24.06.10
Сообщения: 2686
Рейтинг: 543
|
Добавлено: 10/01/12 в 14:32 |
да дело не в винтах, на пыхе - ясен будет медленнее) в его случае, пока мультикурл полностью не отработает для текущего набора подзаданий, управление назад в скрипт он не вернёт, там "события" нужно эмулировать и самому всё дёргать, кроме того
А в случае Пайтона это происходит потому, как Global Lock JIT-а, что б его, но в целом, это один из тех немногих случаев, для которых нужна истинная true-многопоточность, и когда она действительно нужна, можно использовать multiprocessing, фактически, это тот же форк, но только не wget-а а самого себя. Ясен, всегда нужно синхронизироваться и т.д. но для этого случая, сойдёт и так (ну или просто queue, multiprocessing.Pool и т .д.)
это:
Код: |
from threading import Thread
class Downloader(Thread):
def __init__(self, url):
Thread.__init__(self)
|
замени на:
Код: |
from multiprocessing import Process
class Downloader(Process):
def __init__(self, url):
super(Downloader, self).__init__()
|
ну а вообще нужно свой событийный пул делать, и подкидывать новые задания, когда какое-то одно отработает
|
|
|
|
С нами с 21.02.11
Сообщения: 50
Рейтинг: 30
|
Добавлено: 21/01/12 в 00:59 |
atrius писал: | Надо написать программку на С++, которая в параметрах запуска примет N-urlов, ПАРАЛЛЕЛЬНО их скачает, а контент каждого положит в файл с заданным именем и путем. Сейчас задача решается путем параллельного запуска N-wgetов, что очень плохо сказывается на произодительности.
Кто может сделать, пишите в аську 523709. Обсудим бюджет =)
P.S. должно компилиться и работать на x86 и x86_64. Все под линукс. |
Сделаем, не проблема. Отписался на почту.
|
|
Mac, iOS (iPhone, iPad), Android, Win, Linux разработки. Большой опыт, отличный результат.
|
0
|
|
|
С нами с 06.02.12
Сообщения: 11
Рейтинг: 15
|
Добавлено: 09/02/12 в 11:14 |
Могу сбацать на python, файлы будут скачиваться асинхронно, процесс будет *один*, тормозов не будет. Цена 100 баксов. Для работы нужен будет python и библиотека curl.
Контакт: webdatadigger@gmail.com
|
|
|
|
С нами с 31.05.10
Сообщения: 1991
Рейтинг: 487
|
Добавлено: 09/02/12 в 13:08 |
|
|
|
|
Текстовая реклама в форме ответа Заголовок и до четырех строчек текста Длина текста до 350 символов Купить рекламу в этом месте! |
|
Спонсор раздела
|