This commit is contained in:
lovinervy committed 2026-10-07 13:06:47 +05:00
commit c394677d07
59 files changed
+5149

No files matched your search

+115
View File
@@ -0,0 +1,115 @@
# -*- coding: utf-8 -*-
"""Лабораторная работа 6: асинхронный код (asyncio).
Заполните функции ниже. ИНТЕРФЕЙСЫ МЕНЯТЬ НЕЛЬЗЯ — по ним работают
автотесты (tests/test_lab06.py).
Запуск из корня курса:
python lab06_asyncio/solution.py
"""
import asyncio
import os
import sys
import time
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from common.benchmark import make_table
from common.tasks import get_variant
# TODO: впишите свой номер в журнале (1..20)
VARIANT_NUMBER = 0
async def fetch_async(item: int, delay: float):
"""Корутина: имитация I/O-запроса.
await asyncio.sleep(delay) — НЕ блокирует цикл событий.
Вернуть (item, item * item).
"""
# TODO: asyncio.sleep + вернуть результат
raise NotImplementedError
async def fetch_all_async(items: int, delay: float):
"""Все items запросов конкурентно через asyncio.gather.
Вернуть (список результатов, elapsed_seconds), упорядочен по item.
"""
# TODO: gather по всем item -> сортировка не нужна, gather сохраняет порядок
raise NotImplementedError
async def fetch_all_limited(items: int, delay: float, max_concurrent: int):
"""То же, но не более max_concurrent одновременно (asyncio.Semaphore).
Вернуть (список результатов, elapsed_seconds), упорядочен по item.
"""
# TODO: sem = asyncio.Semaphore(...); async with sem: await fetch_async(...)
raise NotImplementedError
async def _fetch_blocking(item: int, delay: float):
"""«Ошибка новичка»: блокирующий time.sleep внутри корутины.
time.sleep НЕ уступает управление — парализует весь event loop.
"""
time.sleep(delay)
return (item, item * item)
async def _blocking_mistake(items: int, delay: float):
"""Все запросы через gather, но с блокирующим сном. Вернуть секунды."""
# TODO: gather по _fetch_blocking, вернуть время
raise NotImplementedError
def measure_blocking_mistake(items: int, delay: float) -> float:
"""Обёртка для тестов: asyncio.run + return секунд."""
# TODO: return asyncio.run(_blocking_mistake(items, delay))
raise NotImplementedError
def main():
v = get_variant(VARIANT_NUMBER)
items, delay = v["io"]["items"], v["io"]["delay"]
print(f"Вариант {v['variant']}: I/O-нагрузка {items} запросов по {delay} c\n")
# --- 1. Async: все запросы сразу ---------------------------------------
t0 = time.perf_counter()
results, t_async = asyncio.run(fetch_all_async(items, delay))
print(f"async, без лимита: {t_async:.3f} c "
f"(упорядочено: {[r[0] for r in results] == list(range(items))})")
# --- 2. Async с лимитом --------------------------------------------------
for mc in (4, 8):
res, t_lim = asyncio.run(fetch_all_limited(items, delay, mc))
print(f"async, лимит {mc}: {t_lim:.3f} c "
f"(идеал ≈ {items / mc * delay:.2f} c)")
# --- 3. Ошибка: time.sleep в корутине -----------------------------------
t_block = measure_blocking_mistake(items, delay)
print(f"async + time.sleep (ошибка!): {t_block:.3f} c "
f"≈ последовательные {items * delay:.2f} c\n")
# --- 4. Сравнение с потоками (лаба 2) ------------------------------------
from concurrent.futures import ThreadPoolExecutor
from common.tasks import io_fetch
t0 = time.perf_counter()
with ThreadPoolExecutor(max_workers=8) as pool:
list(pool.map(io_fetch, range(items), [delay] * items))
t_threads = time.perf_counter() - t0
rows = [("async без лимита", t_async),
("async, лимит 8", t_lim),
("потоки, p=8", t_threads),
("последовательно (ошибка time.sleep)", t_block)]
print(make_table(rows, title="Сравнение подходов к I/O"))
# TODO: в отчёт — таблицу, объяснение разницы потоков и asyncio,
# ответ на вопрос «почему time.sleep убил конкурентность».
if __name__ == "__main__":
main()