Master-X
Форум | Новости | Статьи
Главная » Форум » Программинг, Скрипты, Софт, Сервисы » 
Тема: Написать на С++
цитата
10/01/12 в 08:11
 atrius
Надо написать программку на С++, которая в параметрах запуска примет N-urlов, ПАРАЛЛЕЛЬНО их скачает, а контент каждого положит в файл с заданным именем и путем. Сейчас задача решается путем параллельного запуска N-wgetов, что очень плохо сказывается на произодительности.
Кто может сделать, пишите в аську 523709. Обсудим бюджет =)
P.S. должно компилиться и работать на x86 и x86_64. Все под линукс.
цитата
10/01/12 в 09:57
 ibiz
Оффтопик:
уверен, что по скорости и расходу ресурсов рнр+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;
?>
цитата
10/01/12 в 10:04
 Salvator
на c++ будет дорого и трудноподдерживаемо. рекомендую python multi-threading. фактически, та же асинхронная загрузка, но будет работать везде icon_smile.gif

что-то такое, накидал за 5 минут icon_biggrin.gif:


Код:
#!/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 - список урлов по одному на строку. следи, чтобы имена файлов в урлах не повторялись для текущего каталога.
цитата
10/01/12 в 10:18
 atrius
Всем поставил рейтинга по максимуму
Спасибо
Ушел тестить
цитата
10/01/12 в 11:28
 dDan
Salvator писал:
на c++ будет дорого и трудноподдерживаемо. рекомендую python multi-threading. фактически, та же асинхронная загрузка, но будет работать везде icon_smile.gif

Присоединяюсь. Отлично справляется питончик можно еще для гибкости прикрутить pycurl
цитата
10/01/12 в 11:29
 atrius
Протестировали оба решения.
Текущий способ с запуском нескольких копий wget работает на порядки быстрее.
Не устраивает в текущей схеме то, что при достаточно большой нагрузке сервер складывается тупо от большого кол-ва запущенных процессов, т.е. судя по ТОПу task около 6к, при этом idle около 20%, I|O wait - не более 2%, а время тратится именно на переключение между задачами =( Вот собственно отсюда и растет необходимость в запуске 1 процесса, который параллельно дернет несколько урлов.
цитата
10/01/12 в 13:31
 JM
atrius: а винты у тя там какие и паралельно это скока (количество и какую полосу по mrtg грузят)?
И кусок топа покаж
цитата
10/01/12 в 14:32
 mr. snatch
да дело не в винтах, на пыхе - ясен будет медленнее) в его случае, пока мультикурл полностью не отработает для текущего набора подзаданий, управление назад в скрипт он не вернёт, там "события" нужно эмулировать и самому всё дёргать, кроме того

А в случае Пайтона это происходит потому, как 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/01/12 в 00:59
 ano
atrius писал:
Надо написать программку на С++, которая в параметрах запуска примет N-urlов, ПАРАЛЛЕЛЬНО их скачает, а контент каждого положит в файл с заданным именем и путем. Сейчас задача решается путем параллельного запуска N-wgetов, что очень плохо сказывается на произодительности.
Кто может сделать, пишите в аську 523709. Обсудим бюджет =)
P.S. должно компилиться и работать на x86 и x86_64. Все под линукс.


Сделаем, не проблема. Отписался на почту.
цитата
09/02/12 в 11:14
 webdatadigger
Могу сбацать на python, файлы будут скачиваться асинхронно, процесс будет *один*, тормозов не будет. Цена 100 баксов. Для работы нужен будет python и библиотека curl.
Контакт: webdatadigger@gmail.com
цитата
09/02/12 в 13:08
 LeadFarmer
я так понимаю что твоя задача - написать альтернативный даунлоадер с хорошей подержкой параллельности. Так почему бы не посмотреть в сторону готовых решений: aria2c (http://aria2.sourceforge.net/), axel (http://www.icewalkers.com/Linux/Software/515850/Axel.html, http://www.cyberciti.biz/tips/download-accelerator-for-linux-command-line-tools.html), Multiget.


Эта страница в полной версии