Init
This commit is contained in:
commit
c394677d07
59 files changed
+5149
No files matched your search
@@ -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()
|
||||
Reference in new issue
Block a user