V Londýně probíhá dvoudenní Ubuntu Summit 25.10. Na programu je řada zajímavých přednášek. Zhlédnout je lze také na YouTube (23. 10. a 24. 10.).
Gemini CLI umožňuje používání AI Gemini přímo v terminálu. Vydána byla verze 0.10.0.
Konference OpenAlt 2025 proběhne již příští víkend 1. a 2. listopadu v Brně. Nabídne přibližně 80 přednášek a workshopů rozdělených do 7 tematických tracků. Program se může ještě mírně měnit až do samotné konference, a to s ohledem na opožděné úpravy abstraktů i případné podzimní virózy. Díky partnerům je vstup na konferenci zdarma. Registrace není nutná. Vyplnění formuláře však pomůže s lepším plánováním dalších ročníků konference.
Samsung představil headset Galaxy XR se 4K Micro-OLED displeji, procesorem Snapdragon XR2+ Gen 2, 16 GB RAM, 256 GB úložištěm, operačním systémem Android XR a Gemini AI.
Před konferencí Next.js Conf 2025 bylo oznámeno vydání nové verze 16 open source frameworku Next.js (Wikipedie) pro psaní webových aplikací v Reactu. Přehled novinek v příspěvku na blogu.
Sovereign Tech Fund oznámil finanční podporu následujících open source projektů: Scala, SDCC, Let's Encrypt, Servo, chatmail, Drupal, Fedify, openprinting, PHP, Apache Arrow, OpenSSL, R Project, Open Web Docs, conda, systemd a phpseclib.
Bylo vydáno OpenBSD 7.8. S předběžnou podporou Raspberry Pi 5. Opět bez písničky.
Valkey (Wikipedie) byl vydán v nové major verzi 9.0. Valkey je fork Redisu.
Byly publikovány informace o kritické zranitelnosti v knihovně pro Rust async-tar a jejích forcích tokio-tar, krata-tokio-tar a astral-tokio-tar. Jedná se o zranitelnost CVE-2025-62518 s CVSS 8.1. Nálezci je pojmenovali TARmageddon.
AlmaLinux přinese s verzí 10.1 podporu btrfs. XFS bude stále jako výchozí filesystém, ale instalátor nabídne i btrfs. Více informací naleznete v oficiálním oznámení.
Odkazy
Práce na asynchronnom Djangu začali okolo roku 2020. Je rok 2025. Čo tak sa pozrieť, čo sme za tú dobu získali?
Päť rokov je v oblasti IT veľmi dlhá doba aby async prestal ignorovať aj taký technologický konzervatívec a spiatočník ako ja. Po všetkých tých fantastických blogoch a benchamrkoch som nasadol na vlnu asyncu.
Nie až tak dávno som začal nový projekt v asynchrónnom frameworku FastAPI. Nebudem rozoberať, prečo som sa rozhodol práve pre Django v úlohe ORM. Akonáhle som sa začal trocha hrabať vo vnútornostiach, šokovalo ma ako zle všetko funguje. Tento blog bude o čistom djangu.
Blogy sľubujú výkon. Tak moje konzervatívne skostnatené ja si spustí zastaralý uWSGI a oproti tomu postavím uvicorn. Oba s jedným workerom. Môj naivný view vyzerá ako väčšina dnešných benchmarkov. Veď prečo sa pozerať na komplexnú aplikáciu keď môžeme merať nič?
from django.http.response import JsonResponse def naive_sync(request): return JsonResponse({"status": "ok"}) async def naive_async(request): return JsonResponse({"status": "ok"})
S týmto viewom si spustím benchmark pre 10 simultánnych požiadaviek a 1000 celkovo:
ab -n 1000 -c 10 'http://127.0.0.1:8000/naive/sync/'
Výsledný graf zobrazuje synchrónne volanie v uWSGI, potom synchrónne uvicorn a asynchrónne uvicorn. Vyššie číslo udáva vyššiu priepustnosť.
Obrázok 1: Naivná implementácia
Čo sa stalo? No jednoducho v tomto príklade nemala ako vyniknúť asynchrónnosť. Okrem toho uWSGI je napísaný v C, ale oproti python implementácii je to rozdiel len 2ms na pižiadavku. Nie je to nič, čo by mi žily trhalo v reálnej aplikácii. Tento benchmark je nanič a som si toho vedomý.
Chceme ešte jeden nanič benchmark? Samozrejme! Tak teda to isté so 16 workermi.
Obrázok 2: Naivná implementácia so 16 workermi
Väčšina aplikácií hrabe do databázy a tak si vytvorme pár tabuliek:
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) class Category(models.Model): name = models.CharField(max_length=100) class Document(models.Model): name = models.CharField(max_length=100) authors = models.ManyToManyField(Author, related_name='documents') category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='documents', null=True)
Po naplnení databázy som ešte napísal jeden synchrónny a jeden asynchrónny view.
from asgiref.sync import sync_to_async from django.http.response import JsonResponse from .models import Document def db_sync(request): data = [] for document in Document.objects.order_by('pk'): authors = [] data.append( { "name": document.name, "category": document.category.name, "authors": authors, } ) for author in document.authors.all(): authors.append({"name": author.name}) return JsonResponse({"data": data}) async def db_async(request): data = [] async for document in Document.objects.order_by('pk'): authors = [] data.append( { "name": document.name, "category": (await sync_to_async(getattr)(document, 'category')).name, "authors": authors, } ) async for author in document.authors.all(): authors.append({"name": author.name}) return JsonResponse({"data": data})
Vytvoril som dve prakticky rovnaké funkcie líšiace sa len v dvoch detailoch. Prvým je volanie generátora for. V jednom prípade je synchrónny (for) a v druhom prípade asynchrónny (async for). No a potom je tu táto šialenosť:
(await sync_to_async(getattr)(document, 'category')).name
Python neumožňuje kombinovať synchrónne a asynchrónne funkcie. Napíšete jedinú funkciu asynchrónne a musíte prepísať všetky funkcie, ktoré ju volajú. V postate tým infikujete celý kód. Ak ste tvorcom knižnice, môžete buď napísať knižnicu syncrhónne, alebo asynchrónne, alebo oboma spôsobmi pričom každú funkciu napíšete 2x a bude sa v 99% prípadov líšiť v tomto:
# async async def afunkcia(): ... await ainafunkcia() ... # sync def funkcia(): ... inafunkcia() ...
Django začala ako synchrónna knižnica a postupne sa duplikuje kód. Niektoré „drobnosti“ nie sú doteraz podporované ako napríklad transakcie. No a potom sú tu ešte veci, ktoré sa nedajú prepísať ako napríklad property, kde .category
potrebuje zavolať SQL dotaz, ale propery nie je polymorfná a tak volá len syncrhónny select, ktorý sa nedá zavolať z asynchrónneho kontextu. Zabalíme to teda do sync_to_async
Obrázok 3: Prístup do databázy
To nie je možné!?! Dajme tam 16 workerov. Nech sa ukáže asyncrhṕnnosť.
Obrázok 4: Prístup do databázy so 16 workermi
Ešte väčšia katastrofa, čo? Rozmeňme si to na drobné. Databázový driver, ktorý django používa je synchrónny. Aj keby nebol, tak celá implementácia Djanga je hračkárska a vyzerá takto:
async def aget(self, *args, **kwargs): return await sync_to_async(self.get)(*args, **kwargs)
V tomto momente dochádza k prepnutiu kontextu, čo môže trvať rádovo okolo 1ms. Nie je dostatok vývojárov, aby implementovali a udržiavali Django so skoro každou duplikovanou funkciou. Preto sa len hráme na akože asynchrónnosť. Mimochodom viete, že veľa vývojárov vo svojich knižniciach overriduje save, aby tam pridali napríklad nejakú logiku, ja neviem date_created = now
? Teraz to funguje pretože asave
vyzerá takto: sync_to_async(self.save)
. Teraz si predstavte ako sa django knižnice začnú rozpadávať až sa začne reálne implementovať async. Celý ekosystém, desaťtisíce knižníc sa musia prepísať.
Nakoniec ešte doplním úpravu vďaka ktorej sa spustia len 2 dotazy namiesto 300:
def db_opt_sync(request): data = [] for document in Document.objects.order_by('pk').prefetch_related('authors').select_related('category'): authors = [] data.append( { "name": document.name, "category": document.category.name, "authors": authors, } ) for author in document.authors.all(): authors.append({"name": author.name}) return JsonResponse({"data": data}) async def db_opt_async(request): data = [] async for document in Document.objects.order_by('pk').prefetch_related('authors').select_related('category'): authors = [] data.append( { "name": document.name, "category": (await sync_to_async(getattr)(document, 'category')).name, "authors": authors, } ) async for author in document.authors.all(): authors.append({"name": author.name}) return JsonResponse({"data": data})
Obrázok 5: Prístup do databázy so 16 workermi po optimalizácii
Čo som vlastne chcel povedať? Neverte všetkým sladkým rečiam v blogoch. Python má svoju filozofiu „explicit is better“ a nej podriadil aj implementáciu async. Autori knižníc sa teraz musia rozhodnúť, či budú písať synchrónne, asynchrónne, alebo budú svoj kód duplikovať, budú mať 2x viac práce a 2x viac chýb. Pritom v dynamickom jazyku s tak neskorou adaptáciou async / await nebolo farbenie vôbec nevyhnutné. Škoda. Z môjho pohľadu premárnená príležitosť urobiť lepší jazyk.
Tiskni
Sdílej:
Keďže sa k blogu nedá priložiť súbor prikladám tu. Veľa sa tu na abclinuxu od mojej poslednej návštevy nezmenilo. Akurát ja som o dosť starší, šedivejší a bývam s 10 mačkami v dome.
Veľa sa tu na abclinuxu od mojej poslednej návštevy nezmenilo. Akurát ja som o dosť starší, šedivejší a bývam s 10 mačkami v dome.
To je teda ale smutný příběh.
Smutný ani nie, ale 10 mačiek je dobrý začiatok konverzácie :P Sám nie som, mám partnerku, ktorá má rada mačky, veľa cestujem, mám catsittera kým som preč, veľa koníčkov, aktivít. Škoda akurát, že dni nemajú viac hodín.
az na to ze async nema s vyuzitim cpu cores moc spolecneho ...
na tyto strandy jsou multiprocess a multithread moduly + concurrent.
Async kód využíva kooperatívny multitasking. Niečo, čo vzniklo v dobách jednoprocesorových strojov. Spoliehať sa len na async znamená využívať jediné jadro. Ak sa bavíme o pythone tak správnou cestou je multiprocessing, alebo subinterpretery alebo novy no-GIL. Inak sa bude striedavo využívať jediné jadro.
Správnym využitím async je v prípadoch, keď sa čaká na IO, ale aj vtedy môže byť rozumnejšie kombinovať multiprocessing s asyncom a nemať jeden veľký loop pri veľkom množstve spojení s väčšou priepustnosťou.
Sám by som rád písal čistý async kód, ale knižnice, ktoré používam nie sú prepísané do async a nik ich do async celkom neche prepísať, lebo by bolo potrebné prepísať komplet kód, ktorý ich využíva a vlastne musel by sa infikovať celý ekosystém.
Na limity databázy nenarážam. Používam PostgreSQL 17 s nastavenými max 100 connections.