In das Thema IO-URING eingelesen

This commit is contained in:
Fischlurch 2026-07-10 02:57:34 +02:00
parent 00e8460d1c
commit 10f155d1a3

View file

@ -309,6 +309,14 @@
<node CREATED="1779396306814" ID="ID_1325281102" LINK="https://en.wikipedia.org/wiki/Io_uring" MODIFIED="1779396315914" TEXT="Wikipedia">
<node CREATED="1779397158957" ID="ID_635788695" LINK="https://web.archive.org/web/20251010072644/https://kernel.dk/io_uring.pdf" MODIFIED="1779397176550" TEXT="verlinkt auf Einf&#xfc;hrungs-Artikel: &#xbb;Efficient IO with io_uring&#xab;"/>
<node CREATED="1779397215245" ID="ID_533486044" LINK="https://lwn.net/Articles/810414/" MODIFIED="1779397234502" TEXT="LWN: rapid growth of io_uring (2020)"/>
<node CREATED="1783367993803" ID="ID_1431968418" LINK="https://towardsdev.com/io-uring-vs-epoll-syscall-overhead-linux-performance-a3d7fcc6c9b9?gi=3c0154f883b2" MODIFIED="1783368130857" TEXT="Medium.com: The Linux I/O Interface That Finally Makes Sense">
<node CREATED="1783368130854" ID="ID_478257500" LINK="https://web.archive.org/web/20260706200044/https://towardsdev.com/io-uring-vs-epoll-syscall-overhead-linux-performance-a3d7fcc6c9b9?gi=da9a38a5a4e5" MODIFIED="1783368133389" TEXT="A"/>
</node>
<node CREATED="1783368328751" ID="ID_1994767905" LINK="https://unixism.net/2020/04/io-uring-by-example-article-series/" MODIFIED="1783368342820" TEXT="IO_URING by example (2020)">
<node CREATED="1783368348940" ID="ID_888420188" LINK="https://github.com/shuveb/io_uring-by-example" MODIFIED="1783368354081" TEXT="zugeh&#xf6;riger Github"/>
</node>
<node CREATED="1783370353779" ID="ID_72316824" LINK="https://www.reddit.com/answers/f06c7939-9e61-4d8b-96a0-45180c7ef398/?q=%C3%9Cberblick+io_uring+in+Linux&amp;source=PDP" MODIFIED="1783370359891" TEXT="Reddit-&#xdc;bersichtsseite"/>
<node CREATED="1783370514114" ID="ID_1349175602" LINK="https://arxiv.org/abs/2512.04859" MODIFIED="1783370550553" TEXT="Interessant: arXiv &#x2014; High-Performance DBMSs with io_uring: When and How to use it"/>
</node>
<node CREATED="1779399048372" ID="ID_1376049416" LINK="https://unixism.net/loti/" MODIFIED="1779399068596" TEXT="&#xbb;Lord of the uring&#xab;"/>
</node>
@ -440,16 +448,428 @@
</node>
</node>
</node>
<node CREATED="1783380531260" ID="ID_469108654" MODIFIED="1783380548076" TEXT="mit dem Thema vertraut machen....">
<node CREATED="1783380549407" ID="ID_1386950252" MODIFIED="1783380553917" TEXT="grunds&#xe4;tzich">
<node CREATED="1783380554930" ID="ID_840014622" MODIFIED="1783380581481">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
AsyncIO f&#252;r <i>sehr hohen</i>&#160;throughput
</p>
</body>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
also ehr im Bereich von Millionen Requests / sec
</p>
</body>
</html>
</richcontent>
<node CREATED="1783380657844" ID="ID_1057905414" MODIFIED="1783380667920" TEXT="erst da macht sich der Kontext-Switch bemerkbar"/>
<node CREATED="1783380668713" ID="ID_1392613640" MODIFIED="1783380678765" TEXT="f&#xfc;r tausende Requests/sec reicht ein Threadpool"/>
</node>
<node CREATED="1783380582620" ID="ID_188672487" MODIFIED="1783380656505" TEXT="aber: Files sind immer &quot;ready&quot; und ePoll meldet nur das">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
deshalb war die Behandlung von Files stets etwas asymetrisch. Auch wenn der Socket <i>ready</i>&#160;ist, kann er dann doch noch blocken, wenn das System unter Druck steht.
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1783380681615" ID="ID_849345355" MODIFIED="1783380696024" TEXT="das ist f&#xfc;r uns das zentrale Argument">
<icon BUILTIN="back"/>
</node>
<node CREATED="1783382094070" ID="ID_434911517" MODIFIED="1783382108385" TEXT="au&#xdf;erdem: AIO erlaubt nur direktes, unbuffered IO"/>
</node>
<node CREATED="1783380898163" ID="ID_504375047" MODIFIED="1783380914611" TEXT="Struktur des io_uring-Interface">
<node CREATED="1783381938828" ID="ID_651806818" MODIFIED="1783381950696" TEXT="Lord-of-the-uring-Tutorial">
<icon BUILTIN="info"/>
</node>
<node CREATED="1783380936792" ID="ID_1455615031" MODIFIED="1783380942073" TEXT="zwei Ringbuffer-Kan&#xe4;le">
<node CREATED="1783380943213" ID="ID_1918214029" MODIFIED="1783380969821" TEXT="SQ = submission queue"/>
<node CREATED="1783380958402" ID="ID_371171829" MODIFIED="1783380967381" TEXT="CQ = completion queue"/>
<node CREATED="1783380992795" ID="ID_1515222220" MODIFIED="1783381004376" TEXT="Speicher f&#xfc;r die Ringbuffer is shared (user/kernel space)"/>
<node CREATED="1783381017807" ID="ID_552310788" MODIFIED="1783381022222" TEXT="einrichten">
<node CREATED="1783381034591" ID="ID_1237271759" LINK="https://unixism.net/loti/ref-iouring/io_uring_setup.html#c.io_uring_setup" MODIFIED="1783381043083" TEXT=" io_uring_setup()">
<node CREATED="1783387356135" ID="ID_1660238093" MODIFIED="1783387385016" TEXT="die L&#xe4;nge des Queue-Ringbuffers kann man konfigurieren"/>
</node>
<node CREATED="1783381048487" ID="ID_384071147" MODIFIED="1783381055553" TEXT="dann per mmap in den user-space mappen"/>
</node>
</node>
<node CREATED="1783381397970" ID="ID_1269361958" MODIFIED="1783381400665" TEXT="Verwenden...">
<node CREATED="1783381413665" ID="ID_738123625" MODIFIED="1783381418189" TEXT="add submission queue entry"/>
<node CREATED="1783381440513" ID="ID_1540836016" LINK="https://unixism.net/loti/ref-iouring/io_uring_enter.html#c.io_uring_enter" MODIFIED="1783381479636" TEXT="io_uring_enter()">
<node CREATED="1783381449741" ID="ID_1923740843" MODIFIED="1783381497303" TEXT="triggert den Kernel an: neue SQE da">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
man kann auch mehrere Eintr&#228;ge hinzuf&#252;gen und dann antriggern
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1783381503670" ID="ID_176407271" LINK="https://unixism.net/loti/tutorial/sq_poll.html#sq-poll" MODIFIED="1783381536644" TEXT="oder Submisssion-Queue-Polling verwenden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
dann erkennt der Kernel sebst&#228;ndig, wenn was neues in der Queue ist
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1783381563444" ID="ID_1738464780" MODIFIED="1783381590147" TEXT="kann auch warten bis eine gewisse Zahl an CQ Entries zur&#xfc;ckgeschickt wurde"/>
</node>
<node CREATED="1783381611534" ID="ID_1396608178" MODIFIED="1783381625024" TEXT="ein CQE pro SQE, mit Ergebnis-Status">
<node CREATED="1783387631984" ID="ID_888714962" MODIFIED="1783387642585" TEXT="werden verbunden durch einen user_data-Pointer"/>
<node CREATED="1783387674355" ID="ID_1734790893" MODIFIED="1783387688094" TEXT="dieser wird vom Kernel einfach unver&#xe4;ndert durchgereicht"/>
<node BACKGROUND_COLOR="#fefc4e" COLOR="#351d75" CREATED="1783389920263" ID="ID_631311167" MODIFIED="1783389939307" TEXT="Ha! das pa&#xdf;t perfekt auf mein Design der Continuations im Scheduler">
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1783384996718" ID="ID_1183383765" MODIFIED="1783385010780" TEXT="CQ-Entries kommen in beliebiger Reihenfolge (wenn ready)">
<node CREATED="1783385011889" ID="ID_141657481" MODIFIED="1783385016940" TEXT="man kann aber Ordnung erzwingen"/>
</node>
<node CREATED="1783390082574" ID="ID_693582801" MODIFIED="1783390088426" TEXT="Daten / Buffer">
<icon BUILTIN="idea"/>
<node CREATED="1783390090337" ID="ID_1527986562" MODIFIED="1783390107574" TEXT="hier &#xfc;bertr&#xe4;gt sich die Systematik der alten IO-Syscalls"/>
<node CREATED="1783390108838" ID="ID_1250332278" MODIFIED="1783390117912" TEXT="man gibt einen Buffer im User-Process-Space an"/>
<node CREATED="1783390118846" ID="ID_752139916" MODIFIED="1783390138958" TEXT="der Kernel sorgt daf&#xfc;r, da&#xdf; dort die Daten landen"/>
<node CREATED="1783390139733" ID="ID_1637000405" MODIFIED="1783390228531" TEXT="wie er das macht, kann uns egal sein">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
....vermutlich wird der Buffer-Speicher einfach geeignet auch in den Kernel-Space gemapped; jedoch das Setup mit den Command/Completion-Ringbuffern isoliert den User komplett von diesen Fragen. Sehr geschickt!
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
</node>
<node CREATED="1783381920148" ID="ID_1220852513" MODIFIED="1783381925793" TEXT="low-level-Interface">
<node CREATED="1783381965202" ID="ID_1728181714" MODIFIED="1783381975125" TEXT="Tutorial: erst einmal redv() verstehen...">
<node CREATED="1783382282094" ID="ID_1820629134" MODIFIED="1783446293619" TEXT="scatter/gather-IO bzw. vectored IO">
<linktarget COLOR="#fdfdca" DESTINATION="ID_1820629134" ENDARROW="Default" ENDINCLINATION="1190;0;" ID="Arrow_ID_836559053" SOURCE="ID_668632489" STARTARROW="None" STARTINCLINATION="619;22;"/>
</node>
<node CREATED="1783382409880" ID="ID_1027835294" MODIFIED="1783382419498" TEXT="bekommt eine Liste von Auftrags-Structs">
<node CREATED="1783382430363" ID="ID_1171141321" MODIFIED="1783382439848" TEXT="struct iovec">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<pre http-equiv="content-type" content="text/html; charset=utf-8" class="enlighter-clipboard">struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};</pre>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1783384437400" ID="ID_261205380" MODIFIED="1783384460053" TEXT="transferiert den File-content l&#xfc;ckenlos der Reihe nach in die Buffer"/>
</node>
<node CREATED="1783387732857" ID="ID_1688041268" MODIFIED="1783387775312" TEXT="CQE hat user_date, res/error-code, wie read()"/>
<node CREATED="1783387816253" ID="ID_480695787" MODIFIED="1783387823986" TEXT="SQE ist eine Command-struct">
<node CREATED="1783387824860" ID="ID_1367724603" MODIFIED="1783387827979" TEXT="hat eine Command-ID"/>
<node CREATED="1783387828460" ID="ID_854431460" MODIFIED="1783387836666" TEXT="und dann diverse multi-purpose-fields"/>
<node CREATED="1783387924878" ID="ID_1554669393" MODIFIED="1783387936427" TEXT="Aufrufe sind modelliert nach bekannten IO-Operationen">
<node CREATED="1783388108773" ID="ID_1963002363" MODIFIED="1783388118801" TEXT="bsp: verwendet einen File-Descriptor"/>
<node CREATED="1783388119281" ID="ID_595160605" MODIFIED="1783388126033" TEXT="hat einen Offset in das File"/>
<node CREATED="1783388126544" ID="ID_1557501628" MODIFIED="1783388139315" TEXT="bekommt einen Buffer-pointer oder einen iovec"/>
</node>
</node>
<node CREATED="1783388781316" ID="ID_1265251773" MODIFIED="1783388814792" TEXT="man gibt eine struct io_uring_params an den io_uring_setup()"/>
<node CREATED="1783388646919" ID="ID_1468403550" MODIFIED="1783388660393" TEXT="man definiert sich selbst passende Schnittstellen-Structs">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1783388674071" ID="ID_1871456691" MODIFIED="1783439712989" TEXT="Frage: warum ist das nicht vom Kernel vordefiniert?">
<icon BUILTIN="help"/>
<node CREATED="1783388990307" ID="ID_1963229698" MODIFIED="1783389000855" TEXT="weil das schon ein Abstraktionslayer ist"/>
<node CREATED="1783389001425" ID="ID_149275964" MODIFIED="1783389017213" TEXT="der Kernel definiert lediglich die Basis-structs SQE und CQE"/>
<node CREATED="1783389033526" ID="ID_531781879" MODIFIED="1783389070406" TEXT="die Positionen der Ringbuffer-Kontrollfelder sind quasi-dynamisch"/>
<node CREATED="1783389073434" ID="ID_378448165" MODIFIED="1783389087003" TEXT="sie werden per io_uring_params zur&#xfc;ckgegeben"/>
<node CREATED="1783389088143" ID="ID_1057767628" MODIFIED="1783389106739" TEXT="deshalb ist es sinnvoll, sich da eine Interface-struct dr&#xfc;berzusetzen"/>
</node>
<node CREATED="1783388687235" ID="ID_572599133" MODIFIED="1783388699931" TEXT="diese kann man dann per mmap in den user-space mappen"/>
<node CREATED="1783388891850" ID="ID_54309322" MODIFIED="1783388907891" TEXT="f&#xfc;r das zu mappende &quot;file&quot; gibt es einen File-Descriptor"/>
<node CREATED="1783388921357" ID="ID_788864531" MODIFIED="1783388932860" TEXT="dieser wird von io_uring_setup() zur&#xfc;ckgeliefert"/>
</node>
<node CREATED="1783439723372" ID="ID_70450003" MODIFIED="1783439731172" TEXT="Ringbuffer sind auf Index-Basis implementiert">
<node CREATED="1783439735880" ID="ID_1310555659" MODIFIED="1783439754513" TEXT="es ist ein Array, wobei head und tail als Indices gegeben sind"/>
<node CREATED="1783439755001" ID="ID_339978399" MODIFIED="1783439785005" TEXT="vor dem Zugriff wird der Index modulo die Ringbuffer-L&#xe4;nge genommen"/>
<node CREATED="1783439788873" ID="ID_800063940" MODIFIED="1783439821495" TEXT="Kontrollfelder und die Entry-Arrays liegen im shraed (mmaped) memory"/>
<node CREATED="1783439823932" ID="ID_51197608" MODIFIED="1783439987223" TEXT="die SQ-Entries werden &#xfc;ber eine weitere Indirektion mitgeteilt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Im Submission-Ringbuffer liegt nur eine Index-Nummer, die in ein daneben stehendes weiteres Array zeigt. Im Tutorial hei&#223;t es, das sei so konstruiert worden, um Applikationen zus&#228;tzliche Flexibilit&#228;t zu geben (was ich nicht wirklich verstehe, da ja auch das externe SQ-Array im mmapped-mem liegen mu&#223;)
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1783439999125" ID="ID_1383082691" MODIFIED="1783440018308" TEXT="Sichtbarkeit &#xfc;ber Thread-Grenzen beachten">
<node CREATED="1783440021146" ID="ID_171647218" MODIFIED="1783440029669" TEXT="shared-memory-Programmierung..."/>
<node CREATED="1783440030756" ID="ID_1601251687" MODIFIED="1783440088278" TEXT="braucht immer eine Read-barrier und am Ende eine write-barrier">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
damit man zu Beginn die neuesten Updates vom Kernel mitbekommt, und am Ende dem Kernel die neue Schreib/Lese-Position sichtbar gemacht wird
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1783440089704" ID="ID_1425651981" MODIFIED="1783440102635" TEXT="das gen&#xfc;gt hier, da es sich um single-Producer/Consumer handelt"/>
</node>
</node>
<node CREATED="1783440114398" ID="ID_1217216266" MODIFIED="1783440119000" TEXT="liburing verwenden">
<node CREATED="1783440833117" ID="ID_839873138" MODIFIED="1783440844539" TEXT="stellt ein C-Interface f&#xfc;r den Zugriff auf die Ringbuffer bereit">
<node CREATED="1783440926298" ID="ID_170963361" MODIFIED="1783440944465" TEXT="eine Schnittstellen-struct io_uring">
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node CREATED="1783440846153" ID="ID_1052852486" MODIFIED="1783440859478" TEXT="man kann...">
<node CREATED="1783440860347" ID="ID_134839902" MODIFIED="1783440877595" TEXT="auf den n&#xe4;chsten CQ-Entry blockend warten"/>
</node>
<node CREATED="1783440882234" ID="ID_301034439" MODIFIED="1783440900525" TEXT="die read/write-Barrieren sind verborgen">
<node CREATED="1783440901646" ID="ID_1734627767" MODIFIED="1783440912071" TEXT="stattdessen: io_uring_cqe_seen"/>
<node CREATED="1783442225762" ID="ID_1142061633" MODIFIED="1783442228423" TEXT="io_uring_submit(ring)"/>
</node>
<node CREATED="1783442066344" ID="ID_345729175" MODIFIED="1783442157624" TEXT="stellt high-level parameter-Konstruktoren f&#xfc;r die Operationen bereit">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
im Tutorial-Beispiel: io_uring_prep_readv() f&#252;llt einen SQ-Entry passend aus f&#252;r eine readv-Operation
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1783446631153" ID="ID_235240398" LINK="https://unixism.net/2020/04/io-uring-by-example-part-2-queuing-multiple-requests/" MODIFIED="1783446637597" TEXT="Tutorial: async coply">
<node CREATED="1783446647749" ID="ID_1584749060" MODIFIED="1783446656535" TEXT="alloziert jeweils eine Buffer + einen descriptor"/>
<node CREATED="1783446657178" ID="ID_42171709" MODIFIED="1783446665185" TEXT="h&#xe4;ngt diese als user-data an den Request"/>
<node CREATED="1783446669249" ID="ID_1943056546" MODIFIED="1783446680844" TEXT="macht die Queue erst mit read-requests voll"/>
<node CREATED="1783446681440" ID="ID_1130661279" MODIFIED="1783446690677" TEXT="im descriptor gibt es eine read/write-flag"/>
<node CREATED="1783446691449" ID="ID_557522221" MODIFIED="1783446702668" TEXT="damit wird ein copy-Proze&#xdf; realisiert"/>
<node CREATED="1783446913957" ID="ID_457406046" MODIFIED="1783446917117" TEXT="Komplikationen">
<node CREATED="1783446918040" ID="ID_742805192" MODIFIED="1783447636257" TEXT="anscheinend gibt es einen &quot;retry&quot;, signalisiert mit EAGAIN">
<node CREATED="1783447637802" ID="ID_1480100399" MODIFIED="1783447653363" TEXT="readv() ist nur eine scatter/gather-variante von read/write()"/>
<node CREATED="1783447770285" ID="ID_1587286955" MODIFIED="1783447818026" TEXT="wenn man read() mit Flag O_NONBLOCK aufruft, k&#xf6;nnte der physiche Read trotzdem blocken"/>
<node CREATED="1783447818970" ID="ID_1745751924" MODIFIED="1783447840404" TEXT="in diesem Fall liefert read() einen Fehler (ret=-1) mit Errno == EAGAIN"/>
</node>
<node CREATED="1783446948271" ID="ID_75609256" MODIFIED="1783446958635" TEXT="au&#xdf;erdem k&#xf6;nnen reads/writes k&#xfc;rzer sein als instruiert">
<node CREATED="1783447857789" ID="ID_1707492290" MODIFIED="1783447870607" TEXT="das ist explizit so vorgesehen"/>
<node CREATED="1783447871203" ID="ID_1408811228" MODIFIED="1783447879544" TEXT="kann sein, da&#xdf; das File zuende ist"/>
<node CREATED="1783447880121" ID="ID_1382932735" MODIFIED="1783447896011" TEXT="kann aber auch durch einen Interrupt bewirkt sein"/>
</node>
<node CREATED="1783446959217" ID="ID_1108500089" MODIFIED="1783446972605" TEXT="in beiden F&#xe4;llen mu&#xdf; man einen Request anpassen / nochmal senden"/>
</node>
</node>
</node>
<node CREATED="1783467860105" ID="ID_562346346" MODIFIED="1783467875236" TEXT="spezielle Aspekte">
<node CREATED="1783467876349" ID="ID_76451018" LINK="https://unixism.net/loti/tutorial/sq_poll.html#sq-poll" MODIFIED="1783468042036" TEXT="submission-polling">
<node CREATED="1783467887910" ID="ID_663414334" MODIFIED="1783467904503" TEXT="der Kernel erkennt neue Submission-Queue-Entries von selbst"/>
<node CREATED="1783467913708" ID="ID_1956703105" MODIFIED="1783467937206" TEXT="das spart einen Syscall pro Batch"/>
<node CREATED="1783468073102" ID="ID_1192604598" MODIFIED="1783468079770" TEXT="aktiviert per Flag beim Setup">
<node CREATED="1783468234883" ID="ID_422059492" MODIFIED="1783468250144" TEXT="au&#xdf;erdem: mu&#xdf; das &quot;fixed-files&quot;-feature verwenden"/>
<node CREATED="1783468250631" ID="ID_229494074" MODIFIED="1783468266874" TEXT="das ist ein vorbereitetes Array mit File-Descriptoren"/>
</node>
<node CREATED="1783467937700" ID="ID_1422805249" MODIFIED="1783467948389" TEXT="ABER: Kernel verwendet einen poller-Thread">
<node CREATED="1783467954732" ID="ID_161296285" MODIFIED="1783467979900" TEXT="der verursacht eine nicht-triviale CPU-Last"/>
<node CREATED="1783467981270" ID="ID_1932680351" MODIFIED="1783467997361" TEXT="und er endet von selber, wenn idle; mu&#xdf; dann neu gestartet werden"/>
</node>
<node CREATED="1783468009859" ID="ID_37458969" MODIFIED="1783468021842" TEXT="also &#x27f9; trade-off"/>
</node>
<node CREATED="1783471315936" ID="ID_238162094" MODIFIED="1783471325172" TEXT="Completions entnehmen">
<node CREATED="1783471326168" ID="ID_1768891087" MODIFIED="1783471336770" TEXT="es gibt einen blocking poll"/>
<node CREATED="1783471337414" ID="ID_1463733161" MODIFIED="1783471345321" TEXT="man kann aber peek-Funktionen verwenden"/>
<node CREATED="1783471346034" ID="ID_821102680" MODIFIED="1783471359503" TEXT="das geht auch f&#xfc;r einen Batch von Entries"/>
</node>
<node CREATED="1783469960153" ID="ID_1792704761" LINK="https://unixism.net/loti/tutorial/link_liburing.html#link-liburing" MODIFIED="1783471296410" TEXT="man kann Jobs sequentiell verketten">
<node CREATED="1783469982826" ID="ID_1031698216" MODIFIED="1783469991377" TEXT="dann k&#xf6;nnen sie nur der Reihe nach laufen"/>
<node CREATED="1783469992517" ID="ID_1177264229" MODIFIED="1783470001469" TEXT="nat&#xfc;rlich erzeugt das so einige Komplikationen"/>
<node CREATED="1783470003243" ID="ID_1005057440" MODIFIED="1783470013684" TEXT="und: eine solche Kette kann vorzeitig scheitern"/>
</node>
<node CREATED="1783470066077" ID="ID_858165857" LINK="https://unixism.net/loti/tutorial/fixed_buffers.html" MODIFIED="1783470085644" TEXT="&#xbb;fixed buffers&#xab; direkt shared gemapped">
<node CREATED="1783470086753" ID="ID_522385315" MODIFIED="1783470095701" TEXT="man mu&#xdf; dazu bestimmte Buffer vorher registrieren"/>
<node CREATED="1783470096329" ID="ID_1191315406" MODIFIED="1783470104274" TEXT="dann gibt man nur noch den Index des Buffers an"/>
<node CREATED="1783470104964" ID="ID_2685011" MODIFIED="1783470118664" TEXT="das geht nat&#xfc;rlich nur f&#xfc;r bestimmte Lese/Schreiboperationen"/>
<node CREATED="1783470119428" ID="ID_931891459" MODIFIED="1783470187977" TEXT="Vorteil: keine Kopie der Daten">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
weil der Buffer shared in den Client-Process-Space gemapped ist, mu&#223; der Kernel keine Daten mehr explizit in den Ziepuffer im Proze&#223; kopieren
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1783470603776" ID="ID_492007892" LINK="https://unixism.net/loti/tutorial/register_eventfd.html" MODIFIED="1783470629736" TEXT="kann per poll/epoll signalisieren da&#xdf; eine io_uring-completion vorliegt"/>
</node>
<node CREATED="1783471563411" ID="ID_1282916061" MODIFIED="1783471571979" TEXT="Async-Server-Patterns">
<node CREATED="1783471572703" ID="ID_1157203614" MODIFIED="1783471574044" TEXT="Reactor">
<node CREATED="1783471575007" ID="ID_1734284682" MODIFIED="1783471584374" TEXT="ein Thread der Requests dispatched"/>
<node CREATED="1783471588564" ID="ID_452380465" MODIFIED="1783471606480" TEXT="nimmt Requests entgegen und gibt sie an einen passenden Handler weiter"/>
<node CREATED="1783471897570" ID="ID_1140725129" MODIFIED="1783471919980" TEXT="Charakteristik: ein Reactor reagiert auf Readiness">
<node CREATED="1783471922698" ID="ID_1198048918" MODIFIED="1783471930114" TEXT="typisch f&#xfc;r poll / epoll"/>
<node CREATED="1783471930679" ID="ID_79266399" MODIFIED="1783471942404" TEXT="das Event ist, wenn der Socket ready ist"/>
<node CREATED="1783471943836" ID="ID_1316391544" MODIFIED="1783471950639" TEXT="danach macht der Handler das IO"/>
</node>
</node>
<node CREATED="1783471952182" ID="ID_46196379" MODIFIED="1783471954085" TEXT="Proactor">
<node CREATED="1783471954799" ID="ID_526206128" MODIFIED="1783471962028" TEXT="wie der Reactor: ein Handler-Thread"/>
<node CREATED="1783471962649" ID="ID_415612091" MODIFIED="1783471971307" TEXT="aber hier sind die Events bereits Completions"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1783472019223" ID="ID_1612025217" MODIFIED="1783472086097" TEXT="Achtung: Backpressure notwendig">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1783472033373" ID="ID_662077901" MODIFIED="1783472046527" TEXT="man darf nur so viele Events auf den Weg schicken..."/>
<node CREATED="1783472047042" ID="ID_47181594" MODIFIED="1783472070378" TEXT="...wie man derzeit Completions gleichzeitig handhaben kann"/>
<node CREATED="1783472070951" ID="ID_277160689" MODIFIED="1783472080389" TEXT="sonst explodiert Speicher/Resourcen-Nutzung"/>
</node>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1519001955679" ID="ID_65625223" MODIFIED="1779386731937" TEXT="Demo-Inhalte">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1779504843301" ID="ID_1215238444" MODIFIED="1779504961470" TEXT="Idee">
<icon BUILTIN="idea"/>
<node CREATED="1779504852591" ID="ID_628756969" MODIFIED="1779504956035" TEXT="ein Raw-Video-File framewise einlesen">
<linktarget COLOR="#d60714" DESTINATION="ID_628756969" ENDARROW="Default" ENDINCLINATION="497;-40;" ID="Arrow_ID_347382746" SOURCE="ID_649621958" STARTARROW="None" STARTINCLINATION="347;-14;"/>
<node CREATED="1779504852591" ID="ID_628756969" MODIFIED="1783643338271" TEXT="ein Raw-Video-File framewise einlesen">
<linktarget COLOR="#d60714" DESTINATION="ID_628756969" ENDARROW="Default" ENDINCLINATION="626;-59;" ID="Arrow_ID_347382746" SOURCE="ID_649621958" STARTARROW="None" STARTINCLINATION="347;-14;"/>
<node CREATED="1783641376247" HGAP="32" ID="ID_1978377711" MODIFIED="1783641391758" TEXT="ist einfach" VSHIFT="3"/>
</node>
<node CREATED="1779504863066" ID="ID_986008832" MODIFIED="1779504921775" TEXT="jeden Frame in den Output-Code aus dem Video-output-Vortrag schicken"/>
<node CREATED="1783642371760" ID="ID_622863035" MODIFIED="1783642377238" TEXT="Konstruktions-Schema">
<node CREATED="1783642378650" ID="ID_460419" MODIFIED="1783642391427" TEXT="naheliegend: einen Proactor zeigen">
<node CREATED="1783642938966" ID="ID_1117409154" MODIFIED="1783642955536" TEXT="m&#xe4;&#xdf;ig sinnvoll"/>
<node CREATED="1783642956739" ID="ID_141690825" MODIFIED="1783642968326" TEXT="hier nur ein Consumer"/>
</node>
<node CREATED="1783642985618" ID="ID_169416260" MODIFIED="1783642994611" TEXT="oder einen pull-Worker">
<node CREATED="1783642995707" ID="ID_216666777" MODIFIED="1783642999794" TEXT="das w&#xe4;re n&#xe4;her an Lumiera"/>
<node CREATED="1783643000727" ID="ID_737342556" MODIFIED="1783643655114" TEXT="der w&#xfc;rde jeweils nur die Queue ausr&#xe4;umen"/>
<node CREATED="1783643039177" ID="ID_1046849410" MODIFIED="1783643729328" TEXT="und eine Flag am Buffer setzen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...also eine kleine State-machine implementieren: Completion-Entries entgegennehmen, schauen ob komplett und partiell, partielle nochmal auf den Weg schicken, Komplette am Buffer markieren. Danach w&#252;rde die Render-Aktion laufen, und lediglich schauen, ob die Daten in &#187;ihrem&#171; Buffer schon da sind. Alles per Modulus gesteuert.
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1783643047694" ID="ID_887714759" MODIFIED="1783643329861" TEXT="verwende einen Buffer-Ring">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
der sollte dann die gleiche Gr&#246;&#223;e haben wie der Kernel-Ringbuffer; man w&#252;rde damit einen Task sofort in den passenden Buffer-Slot schicken
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1783643760643" ID="ID_697288367" MODIFIED="1783644233208" TEXT="braucht Flow-Steuerung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Damit das funktioniert, mu&#223; sich das System selbst beobachten: einen EMA f&#252;r den IO-Vorlauf; entsprechend viele Zyklen vorher eine neue IO-Aktion auf den Weg schicken.
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
<node CREATED="1783644313430" ID="ID_170028474" MODIFIED="1783644320854" TEXT="Prototyp entwickeln">
<node CREATED="1783644336145" ID="ID_413309976" MODIFIED="1783644338390" TEXT="Skelett">
<node CREATED="1783644339455" ID="ID_932453573" MODIFIED="1783644342669" TEXT="CMake"/>
<node CREATED="1783644343706" ID="ID_481307677" MODIFIED="1783644354828" TEXT="ein GTK-Rahmen (wie letztes Jahr)"/>
<node CREATED="1783644357376" ID="ID_1687423764" MODIFIED="1783644363091" TEXT="ein Worker-Thread"/>
<node CREATED="1783644382004" ID="ID_222096554" MODIFIED="1783644392847" TEXT="Handler">
<node CREATED="1783644394013" ID="ID_599467746" MODIFIED="1783644398783" TEXT="Completion-Handler"/>
<node CREATED="1783644399671" ID="ID_1684157516" MODIFIED="1783644406037" TEXT="Submission-Handler"/>
<node CREATED="1783644407569" ID="ID_69520880" MODIFIED="1783644412668" TEXT="Display-Handler"/>
</node>
<node CREATED="1783644425567" ID="ID_238189215" MODIFIED="1783644429274" TEXT="Flow-Steuerung">
<node CREATED="1783644430659" ID="ID_269686877" MODIFIED="1783644452555" TEXT="Aufrabe: Vorlauf steuern">
<node CREATED="1783644529049" ID="ID_486151338" MODIFIED="1783644875737" TEXT="zwei Phasen (Chase/Lock)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
In der Chase-Phase werden blank-Frames ausgegeben, solange bis wir Frames mit gen&#252;gend Vorlauf im Speicher haben. Danach, in der Lock-Phase ist eine Relation zwischen der rotierenden Buffer-Position und dem aktuellen Flip gesetzt. Ab dem Punkt kann man N Frames im Voraus die IO-Aktion losschicken.
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1783644878986" ID="ID_629406693" MODIFIED="1783644997672" TEXT="Problem: Anfangs-Spitze">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Zu Beginn schicken wir M Frames auf den Weg; die brauchen u.U l&#228;nger. Sch&#246;n w&#228;re es nat&#252;rlich, wenn man diesen Selbs-regulierenden Mechanismus auch live zeigen k&#246;nnte
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1781400461948" FOLDED="true" ID="ID_1876863038" MODIFIED="1783362593603" TEXT="Laptop">
@ -1779,9 +2199,13 @@
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
<icon BUILTIN="wizard"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1779504789243" ID="ID_649621958" MODIFIED="1779504956035" TEXT="Kl&#xe4;ren: kann man mit IO_URING gezielt bestimmte Bereiche eines Files lesen?">
<arrowlink COLOR="#d60714" DESTINATION="ID_628756969" ENDARROW="Default" ENDINCLINATION="497;-40;" ID="Arrow_ID_347382746" STARTARROW="None" STARTINCLINATION="347;-14;"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1779504789243" ID="ID_649621958" MODIFIED="1783643338271" TEXT="Kl&#xe4;ren: kann man mit IO_URING gezielt bestimmte Bereiche eines Files lesen?">
<arrowlink COLOR="#d60714" DESTINATION="ID_628756969" ENDARROW="Default" ENDINCLINATION="626;-59;" ID="Arrow_ID_347382746" STARTARROW="None" STARTINCLINATION="347;-14;"/>
<icon BUILTIN="help"/>
<node CREATED="1783446197275" ID="ID_1248460230" MODIFIED="1783446216012" TEXT="IO_URING stellt andere IO-Operationen in asynchroner Weise bereit"/>
<node CREATED="1783446217077" ID="ID_668632489" MODIFIED="1783446293619" TEXT="insofern ja: readv() / writev() k&#xf6;nnen beliebige Teilbereiche eines Files lesen/schreiben">
<arrowlink COLOR="#fdfdca" DESTINATION="ID_1820629134" ENDARROW="Default" ENDINCLINATION="1190;0;" ID="Arrow_ID_836559053" STARTARROW="None" STARTINCLINATION="619;22;"/>
</node>
</node>
</node>
</node>