import time
import aiohttp
from local_server import serve
from dataloader_rs import PyAsyncDataset, PyDataloader
def slow_answer(path: str, headers) -> tuple[int, bytes]:
time.sleep(0.02) return 200, f"content of {path}".encode()
class Pages(PyAsyncDataset):
def __init__(self, urls: list[str]) -> None:
super().__init__()
self.urls = urls
self.session: aiohttp.ClientSession | None = None
def __len__(self) -> int:
return len(self.urls)
async def __getitem__(self, index: int) -> bytes:
if self.session is None:
self.session = aiohttp.ClientSession()
async with self.session.get(self.urls[index]) as response:
response.raise_for_status()
return await response.read()
async def aclose(self) -> None:
if self.session is not None:
await self.session.close()
def main() -> None:
with serve(slow_answer) as base:
urls = [f"{base}/page/{i}" for i in range(64)]
loader = PyDataloader(
Pages(urls),
batch_size=16,
num_workers=2, item_concurrency=8, transform=lambda index, body: body.decode(), )
start = time.perf_counter()
batches = list(loader)
elapsed = time.perf_counter() - start
print(batches[0][:3], "...")
print(
f"{sum(map(len, batches))} pages of 20 ms each in {elapsed * 1000:.0f} ms "
f"with 16 in flight (one at a time: {len(urls) * 20} ms)"
)
del loader
if __name__ == "__main__":
main()