Почему мой многопоточный загрузчик сокетов на основе Python работает медленнее, чем мой многопоточный загрузчик, использPython

Программы на Python
Ответить Пред. темаСлед. тема
Гость
 Почему мой многопоточный загрузчик сокетов на основе Python работает медленнее, чем мой многопоточный загрузчик, использ

Сообщение Гость »


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

импорт журнала импортировать ОС импортировать повторно импорт сокета импортные носки импорт потоков время импорта из urllib.parse импортировать ParseResult, urlparse, снять кавычки флаг: bool = Истина класс МойПрокси: def __init__(self: "MyProxy", протокол: str, хост: str, порт: int) -> Нет: self.protocol: str = протокол self.host: str = хост self.port: int = порт def setSocks5Proxy(self: "MyProxy", s:socks.socksocket) -> Нет: s.set_proxy(socks.SOCKS5, self.host, self.port) def getHttpProxy(self: "MyProxy") -> str: верните f"{self.protocol}://{self.host}:{self.port}" def getHostName(url: str) -> str | Никто: пытаться: хост: ParseResult = urlparse(url) вернуть хост.имя хоста кроме исключения как e: logging.error(f"ошибка анализа URL:({url}) с {e}") def getFileName(url: str) -> str | Никто: пытаться: хост: ParseResult = urlparse(url) вернуть хост.путь.split("/")[-1] кроме исключения как e: logging.error(f"parseFileName Fail url:({url}) ошибка с {e}") защита download_chunk( URL: str, начало: int, конец: int, dataDict: dict, прокси: MyProxy | Нет = Нет ): хост = getHostName (url) если не хост: глобальный флаг флаг = Ложь если прокси: s = носки.socksocket(socket.AF_INET, сокет.SOCK_STREAM) proxy.setSocks5Прокси(и) еще: s = сокет.сокет(сокет.AF_INET, сокет.SOCK_STREAM) print(threading.current_thread().ident, "start:", time.time()) s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 81920000) s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 81920000) s.connect((хост, 80)) запрос = ( f"GET {url} HTTP/1.1\r\nДиапазон: bytes={start}-{end}\r\nХост: {host}\r\n\r\n" ) s.sendall(request.encode()) ответ = б"" пока правда: данные = s.recv(81920000) если нет данных: перерыв ответ += данные header_delimiter = b"\r\n\r\n" header_end_index = response.find(header_delimiter) если header_end_index != -1: ответ = ответ[header_end_index + len(header_delimiter) :] dataDict[start] = ответ print(threading.current_thread().ident, "конец:", time.time()) # 关闭连接 с.закрыть() def download (url: str, savePath: str, num_threads: int, прокси: MyProxy | None = None): хост: str = getHostName (url) defaultFileName: str = getFileName(url) если прокси: s = носки.socksocket(socket.AF_INET, сокет.SOCK_STREAM) proxy.setSocks5Прокси(и) еще: s = сокет.сокет(сокет.AF_INET, сокет.SOCK_STREAM) s.connect((хост, 80)) request = f"HEAD {url} HTTP/1.1\r\nХост: {хост}\r\n\r\n" s.sendall(request.encode()) ответ = s.recv(4096).decode() имя_файла = re.search(r'Content-Disposition:.*filename="(.+)"', ответ) имя_файла = имя_файла.группа(1), если имя_файла, иначе имя_файла по умолчанию имя файла = снять кавычки (имя файла) content_length = int(response.split("Content-Length: ")[1].split("\r\n")[0]) # print(f"{response}") с.закрыть() logging.info(f"文件名: {filename}, 文件大小: {content_length}") если os.path.isdir(savePath): savePath = os.path.join(savePath, имя файла) элиф os.path.isfile(savePath): logging.warning(f"savePath({savePath}) существует, будет скрыт") еще: logging.error(f"savePath({savePath}) не существует, будет создан") os.madeirs(savePath, Exist_ok=True) savePath = os.path.join(savePath, имя файла) chunk_size = длина_контента // количество_потоков список потоков: список[threading.Thread] = [] dataDict: dict = {} начало = 0 конец = 0 для меня в диапазоне (num_threads): конец = ( (start + chunk_size - 1), если (i < число_потоков — 1) иначе (длина_контента — 1) ) нить = резьба.Thread( target=download_chunk, args=(url, начало, конец, dataDict, прокси) ) поток.start() thread_list.append(поток) начало = конец + 1 для потока в thread_list: поток.join() если нет флага: logging.error("Ошибка загрузки") возвращаться с open(savePath, "wb+") в виде файла: для ключа в сортировке (dataDict.keys()): file.write(dataDict[ключ]) logging.info("Готово!") logging.basicConfig(уровень="ИНФО") startTime = время.время() logging.info(startTime) скачать( url="https://download.zerotier.com/dist/ZeroTier%20One.msi", # url="https://releases.ubuntu.com/20.04.6/ubu ... -amd64.iso", savePath="E:", число_потоков = 8, proxy=MyProxy("socks5", "127.0.0.1", 10808), ) logging.info(time.time() - startTime) выше — мой загрузчик сокетов,

импорт журнала импортировать ОС импорт потоков время импорта запросы на импорт из urllib.parse импортировать urlparse класс МойПрокси: def __init__(self: "MyProxy", протокол: str, хост: str, порт: int) -> Нет: self.protocol: str = протокол self.host: str = хост self.port: int = порт def getHttpProxy(self: "MyProxy") -> str: верните f"{self.protocol}://{self.host}:{self.port}" класс DownloadThread(threading.Thread): защита __init__( я: "DownloadThread", URL: ул., начальный_байт: интервал, конечный_байт: интервал, имя файла: ул, прокси: dict | Нет = Нет, ) -> Нет: threading.Thread.__init__(self) self.url = URL self.start_byte = стартовый_байт self.end_byte = конечный_байт self.filename = имя файла self.proxies = прокси def run(self: "DownloadThread"): headers = {"Диапазон": f"bytes={self.start_byte}-{self.end_byte}"} ответ = запросы.получить(# noqa: S113 self.url, headers=заголовки, прокси=self.proxies ) с open(self.filename, "r+b") в качестве файла: file.seek(self.start_byte) file.write(ответ.контент) print(f"Загружено {self.filename} байт {self.start_byte}-{self.end_byte}") def main(url: str, savePath: str, num_threads: int = 1, proxy: MyProxy | None = None): имя_файла = urlparse(os.path.basename(url)).path # 判断保存路径 если os.path.isdir(savePath): savePath = os.path.join(savePath, имя файла) элиф os.path.isfile(savePath): logging.warning(f"savePath({savePath}) существует, будет скрыт") еще: logging.error(f"savePath({savePath}) не существует, будет создан") os.madeirs(savePath, Exist_ok=True) savePath = os.path.join(savePath, имя файла) прокси = Нет если прокси: прокси = {"http": proxy.getHttpProxy(), "https": proxy.getHttpProxy()} ответ = запросы.head(url, таймаут=60, прокси=прокси) total_size = int(response.headers.get("Content-Length", 0)) print("total_size:", total_size) part_size = total_size // количество_потоков темы = [] с open(savePath, "wb"): проходить для меня в диапазоне (num_threads): начальный_байт = размер_части * я конечный_байт = общий_размер, если я == число_потоков - 1, иначе начальный_байт + размер_части - 1 поток: DownloadThread = DownloadThread( URL, start_byte, end_byte, savePath, прокси ) поток.start() threads.append(поток) за т в темах: t.join() print("Загрузка завершена") если __name__ == "__main__": start_time = время.время() основной( # url="https://releases.ubuntu.com/20.04.6/ubu ... -amd64.iso", # url="https://zenlayer.dl.sourceforge.net/pro ... _Win64.exe", url="https://saimei.ftp.acc.umu.se/cdimage/a ... etinst.iso", savePath="E:\\", число_потоков = 1, proxy=MyProxy("http", "127.0.0.1", 10809), ) конечное_время = время.время() print(f"耗时: {end_time - start_time} 秒") выше — загрузчик моего запроса, В большинстве случаев запросы выполняются быстрее, чем загрузчик сокетов. какая часть является причиной того, что мой загрузчик сокетов работает так медленно?

я пытаюсь использовать s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 81920000), чтобы увеличить размер буфера, но это не работает
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Почему мой многопоточный ввод-вывод Java медленнее последовательного?
    Anonymous » » в форуме JAVA
    0 Ответы
    30 Просмотры
    Последнее сообщение Anonymous
  • Почему мой многопоточный ввод-вывод Java медленнее последовательного?
    Anonymous » » в форуме JAVA
    0 Ответы
    27 Просмотры
    Последнее сообщение Anonymous
  • Почему мой многопоточный ввод-вывод Java медленнее последовательного?
    Anonymous » » в форуме JAVA
    0 Ответы
    13 Просмотры
    Последнее сообщение Anonymous
  • Почему мой многопоточный ввод-вывод Java медленнее последовательного?
    Anonymous » » в форуме JAVA
    0 Ответы
    19 Просмотры
    Последнее сообщение Anonymous
  • Использование параллелизма в Java делает программу медленнее (в четыре раза медленнее!)
    Anonymous » » в форуме JAVA
    0 Ответы
    8 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»