yt-dlp-gui/perf_report.py
loop-uh 581a68c1f6 YouTube: запасной путь через пул egress-туннелей
Если все прямые видеосерверы ролика заблокированы провайдером (YouTube даёт
на ролик 2-3 кластера, бывает — все под блокировкой) или 6 с нет ни байта,
RaceFD разбирает ролик через egress (ссылка привязана к IP запросившего) и
качает куски через пул SOCKS-туннелей — по туннелю на поток, т.к. провайдер
режет каждое соединение до узла. Прямые попытки идут параллельно.

Пул: ytgrab-egress-pool.target, 16 туннелей 127.0.0.1:18110-18125
(YTG_EGRESS_POOL). Egress-путь не пишется в общий бан-лист и рейтинг
серверов. Метрика egress_bytes в perf. Зависимости: requests, PySocks.
2026-09-22 23:16:47 +03:00

50 lines
2.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Сводка производительности загрузок: `python perf_report.py [часов]`.
Читает таблицу perf из базы статистики (см. stats.record_perf). Показывает
по сайтам и движкам: сколько загрузок, исходы, время до первого байта,
скорость и как часто пришлось менять видеосервер (признак DPI).
"""
import sys
import time
import hostban
import stats
def _mb(v):
return "—" if v is None else f"{v / 1048576:.1f}"
def _s(v):
return "—" if v is None else f"{v / 1000:.1f}"
def main() -> None:
hours = int(sys.argv[1]) if len(sys.argv) > 1 else 24
rep = stats.perf_report(hours)
print(f"За {rep['hours']} ч: {rep['rows']} загрузок\n")
for g in rep["groups"]:
print(f"{g['site']} [{g['engine']}]: {g['count']} шт — готово {g['finished']}, "
f"ошибок {g['errors']}, отмен {g['cancelled']}")
if g["error_kinds"]:
print(f" ошибки: {g['error_kinds']}")
print(f" до первого байта: медиана {_s(g['prepare_ms_p50'])} с, "
f"90% {_s(g['prepare_ms_p90'])} с")
print(f" скорость: медиана {_mb(g['speed_p50'])} МБ/с, "
f"худшие 10% {_mb(g['speed_p10'])} МБ/с, медленнее 2 МБ/с: {g['slow_under_2mb']}")
print(f" всего на задачу: медиана {_s(g['total_ms_p50'])} с, 90% {_s(g['total_ms_p90'])} с; "
f"очередь 90% {_s(g['queue_ms_p90'])} с")
if g["engine"] == "racefd":
print(f" смена сервера: {g['mirror_switches']} раз, "
f"непробившихся соединений {g['conn_fail_share'] * 100:.0f}%, "
f"через egress: {g['via_egress']} загрузок")
print()
bans = hostban.listing()
print(f"Заблокированные видеосерверы сейчас (обходим): {len(bans)}")
now = time.time()
for ip, since, until in bans:
print(f" {ip}: в списке {int((now - since) / 60)} мин, ещё {int((until - now) / 60)} мин")
if __name__ == "__main__":
main()