Transcript: Python Async Teil 1 - am Beispiel von Django
Full episode transcript. Timestamps refer to the audio playback.
Ja, hallo liebe Hörerinnen und Hörer, willkommen im Python-Podcast.
Heute ist die 23. Episode, also für uns wieder eine ganz besondere Zahl.
Was machen wir heute? Heute machen wir wieder Async und Multiswelling und sowas.
Und zwar Django Async kommt bald raus und darüber haben wir eine eigene Folge aufgenommen.
Und zwar in dem schönen Wintergarten von Jochen. Ich bin der Dominik.
Und diesmal haben wir natürlich wieder einen Gast. Den kennt ihr vielleicht schon.
Hallo Johannes.
Hallo Dominik. Hallo Jochen.
Und hallo Jochen.
Hallo, genau, auch wieder dabei.
Ja, falls euch irgendwas gefällt oder nicht gefällt,
dann schreibt uns doch wie immer gerne eine E-Mail an
hallo-at-pison-podcast.de
Und wir möchten uns auch gerne noch für ein paar Abonnenten bedanken.
Und zwar haben wir allein auf Spotify
mittlerweile über 1111 Abonnenten.
Herzlichen Dank dafür und wuhuu!
Sehr cool, wir freuen uns, wir finden das toll.
Naja.
Reicht es noch nicht, du willst die Welt verschaffen.
Du guckst zu viele YouTube-Channels,
oder? Ich weiß nicht genau.
Ist das da so üblich?
Ich weiß nicht, ob das beim Podcast auch so üblich ist.
Ach, was denn? Ich habe mich einfach gefreut.
Ja, nee, ist schon toll, aber keine Ahnung.
Ja, und wo wir gerade schon bei so anderen Sachen sind.
Also ihr habt ja vielleicht den Thomas gehört,
der mit uns eine schöne Folge gemacht hat.
Und der hat jetzt seinen Podcast umbenannt.
Also wir hatten ihn das letzte Mal zu wenig erwähnt.
Deswegen müssen wir es auch einmal extra erwähnen.
Der ist ein ziemlich cooler Podcast, den er da hat.
Wie heißt der jetzt, Jochen?
Dads and Stats.
Und er hat Kevin Sisson dabei in einem letzten Talk
und redet über Pi MC3.
Ich glaube, ist sehr hörenswert, die Co-Founder von Pi MC3.
Ja, ich hab's gestern schon gehört, fand's sehr gut.
Also, ja.
Ja, vielen Dank, Thomas, für die nächste tolle Episode.
Ja, und hätte ich jetzt
gar nicht gedacht, ich meine, dass Instagram Python macht,
aber dass sich halt deren Gründer und Ex-CEO
irgendwie so viel mit
Statistik und Machine Learning-Kram so beschäftigt
ist und Data Science. Oder, naja, gut,
das hat er ja vorher nicht so gemacht, aber das macht er jetzt halt,
das fand ich schon sehr interessant und
ja, war auf jeden Fall eine interessante Geschichte.
Ja, hört doch da mal rein, wenn ihr möchtet.
Ja, wir machen heute wieder
Django, vor allen Dingen halt, weil Django 3.1
jetzt im August erscheint und
tatsächlich jetzt mehr Async-Features
unterstützt als in der 3.0-Version, die
seit Dezember draußen ist. Und wir
möchten ein bisschen mit euch darüber reden oder
untereinander darüber reden, was das überhaupt
heißt, was das alles so ist.
Was ist überhaupt dieses Multisprengen? Wir hatten das
in irgendeiner Episode schon mal so ein bisschen angerissen,
vielleicht auch so ein bisschen kurz gesprochen, aber
uns sind noch so ein paar andere Erkenntnisse gekommen und
darüber wollten wir halt so sprechen. Warum
macht man so ein Shred und warum
macht man so ein Multiprocess? Und warum macht man
das dann irgendwie Async? Und warum macht man das mit Async.io?
Und was gibt es dann noch für Alternativen?
Wann braucht man das überhaupt? Und warum?
Und warum vielleicht auch überhaupt nicht?
Irgendwie so.
Ja, wollten wir vielleicht erst noch so ein bisschen News machen?
Oh, News, ja. Du hast natürlich
recht. Neuigkeiten aus der Szene.
Ja, wobei
so wahnsinnig viel gab es nicht. Ich habe mir noch ein paar
Dinge aufgeschrieben. Ich weiß nicht,
ob du das verwendest. Insofern kannst du vielleicht
Pylance. Ach ja.
Ja, sehr gut. Ja, also Pylance
ist ein neues Plugin, was für VS Code rausgekommen ist.
Also ein neuer Language-Server, wenn ich das
richtig verstehe, der eine ziemlich coole Sache macht.
Also mit der Auto-Import-Sätze in VS Code und so
und fast alle Features, die man sonst
so auf PyCharm eher hatte. Und also
ich mag ihn sehr gerne. Hast du ihn auch schon aktiv im Einsatz?
Ich habe das auch schon aktiviert
und finde es auch ziemlich gut. Also
ich mache jetzt gar nicht so viel mit
Type-Annotationen, aber die Verlockung
wird stärker. Ja. Und
das Ding kann da irgendwie einiges rausholen,
ja. Finde ich auch. Tja, Johannes,
da bist du raus, wenn du uns PyCharm, ne?
Ja, tut mir leid, ich habe die Features alle schon.
Ich meine, ich benutze ja auch PyCharm.
Also insofern, ich finde das auch gar nicht schlecht.
Du wurdest dazu gezwungen, habe ich gehört, Jochen.
Naja, mehr oder weniger.
Ich meine, ich finde es ja auch interessant.
Also ab und zu mal andere Dinge verwenden, ist vielleicht gar nicht so schwierig.
Bei uns nutzen wir alle VS Code.
Achso, wer übrigens auch VS Code natürlich nutzt,
ist Daniel Feldtroy, falls ihn kennt,
der Autor von Two Schools of Django,
der ja bald das 3X-Version-Buch rausnimmt.
Und ich war letztens bei ihm ein, zwei Mal in seinem Twitch-Stream,
weil er irgendwie streamt, irgendwie twitcht und er
hat mir versprochen, dass er in Düsseldorf zum Essen
vorbeikommt. Bin natürlich ganz gespannt, ob das
irgendwie nicht nur blöd ist.
Ja, das kann man leicht
versprechen, ne? Solange keine Flugzeuge fliegen und so,
ist das immer irgendwie relativ...
Also ich glaube, ein zweites Mal, als ich da war, hat er gedacht,
oh, warst du nicht der aus Istanbul? Ich so, nee,
das war aus Düsseldorf, aber...
Ja, relativ gesehen...
Ach, Düsseldorf, Istanbul. Kann man sich dann da
Bücher signieren lassen? Ja, also wenn die
Altersdiener auf jeden Fall, ja, das hat er ja auch gesagt,
vielleicht verlieh ich dann sogar dahin und dann
Quatsch mir ein bisschen. Nein, fand ich super.
Wollte ich nur mal kurz erwähnt haben.
Ja, aber es stimmt. Ich gucke in letzter
Zeit auch gerade in
Vorbereitung auf diese Episode, habe ich relativ
viel YouTube-Channels und so geguckt.
Und da verwenden doch sehr viele
VS Code. Du hast dich
vorbereitet? Ja, ausnahmsweise mache
ich ja sonst eigentlich nicht. Es bestehen noch Zeichen und Wunder.
Ja, ich fand es auch sehr unangenehm, ehrlich
gesagt. Ich weiß nicht, ob ich das nochmal machen möchte.
Aber gerade
zum Beispiel, da gab es
eine Serie
von Lukas Langer, der hat
auch VS Code verwendet.
Zu Async.io und so.
Auch sehr empfehlenswert, kommt auch noch
in die Show-Nutzung. Ja, ansonsten
war, glaube ich, irgendwie für 3.7
ist die letzte
Bugfix-Release irgendwie
gerade erschienen. Für 3.6
noch irgendeine Security-
Geschichte, Python, und
das war es dann so ziemlich irgendwie mit
Ja, dann bald ist 3.9 durch, ne?
Ja, bald kommt dann 3.9, genau.
Was ist denn das Tolle an 3.9?
Jetzt hast du jetzt mal gefragt.
Auf dem falschen Fuß erwischt.
Also ich meine, das Tolle an 3.8
ist ja der Walrus-Operator und den wir
auch alle ständig immer benutzen.
Ich wüsste nicht, was in 3.9 neues drin ist.
Doch, also ich habe gehört,
dass zum Beispiel diese
Subinterpreter-Geschichte da
irgendwie mit drin sein soll.
Also das war fraglich eine Zeit
lang und dann gab es... Bitte erkläre
uns dann, was ist ein Subinterpreter?
Ja, das ist im Grunde auch so eine
so eine Methode, um dann halt eventuell,
also, ähm, ja,
um halt den Gil so ein bisschen
loszuwerden oder halt das so ein bisschen...
Gil ist der Global Interpreter-Log, ja?
Ja, da werden wir sicherlich gleich noch ganz viel drüber sprechen.
Genau, die Konsequenzen so ein bisschen zu
mitigieren und das
sollte, ich weiß es nicht,
vielleicht auch so hinterher zählen, ich habe keine Ahnung.
Also, ich habe gehört, Python 3.9 unterstützt einen neuen
Parser und der macht ganz viel anders und deswegen
kann man jetzt auf einmal ganz viele andere Code-Analysen
oder irgendwas benutzen. Ja.
Aber...
Ja, diese Pack-Parser-Geschichte, ja.
Ja, weiß ich aber auch nicht so viel zu.
Also für den normalen Programmierer erstmal keine Unterschiede.
Ja, nicht so richtig viel.
Also muss man sich mal mit beschäftigen.
Vielleicht gibt es auch irgendwelche total coolen Sachen.
Na gut.
Ansonsten Django, genau, war auch 2.2.14 und 3.0.8 sind irgendwie vor kurzem raus.
Ja.
Ja, also Django ist jetzt hart an der Entwicklung zu 3.1.
Und das ist ja das, worüber wir heute reden wollen,
weil es halt tatsächlich diese Async-Features jetzt gibt.
Oder hast du noch mehr News aus der Szene?
Ja, ich habe welche aus dem Hintergrat,
beziehungsweise aus meinem persönlichen Setup.
Oh.
Und zwar, genau, ich weiß nicht, ob man es hören kann,
aber jetzt ist hier, wir haben irgendwie eine große Bohrmaschine genommen
und dann irgendwie hier mal die Außenmauer durchlöchert
und jetzt ist hier tatsächlich kabelbasiertes Netz.
Oh.
Und es könnte sein, dass es jetzt deutlich weniger knackst als vorher.
Also du meinst, weil es weniger
Wi-Fi gibt und jetzt mehr konstantes
Laden. Jetzt gibt es halt richtig ordentliches
Stimmt, ich sehe sogar da hinten das Kabel,
das durch die Wand in den Raum geht.
Genau. Und
eine zweite Geschichte, die auch
neu ist und die ich eigentlich ganz
cool finde, weil ich nicht wusste,
also ich habe das Ding einfach mal so auf Verdacht
gekauft und wusste nicht, ob es geht, aber es ging tatsächlich,
war, ich habe mir so eine
Kaldigit Docking Station
besorgt. Eine was?
Kaldigit. Ja, ja, ja.
Das Ding versorgt gleichzeitig einen Rechner mit Strom, macht irgendwie Thunderbolt und du kannst Monitore dran anschließen.
Und was ich halt da drin habe, also ich habe sozusagen nur noch ein Kabel, das ich halt immer an den Rechner stecke.
Weil ich hatte nämlich jetzt, da ich jetzt Netzwerkkabel habe, das Problem, okay, wie mache ich denn das Netzwerkkabel an meinem Rechner fest?
Der hat ja nur USB-C.
Da so irgendwie so ein Dongle dran zu hängen, der dann so rumbaumelt, ist auch irgendwie etwas unschön.
Zusätzlich zu den ganzen anderen Adaptern und Dongle, die da sowieso schon rumbaumeln.
Ähm, äh, und, ähm, das geht damit halt ganz gut, weil da steckt man einfach Ethernet hinten rein plus irgendwie das, was zum Monitor geht und, äh, hat halt nur ein einziges Kabel, was zum Laptop geht und alles andere, äh, geht dann über die Dockingstation und was tatsächlich funktioniert ist, man hat halt, ich hab da hinten halt dann noch Storage dran und das ist schnell, äh, und, also so eine externe SSD und das ist ordentlich schnell, der Monitor ist so ein, so ein, so ein ultrafein, äh, LG 5K und da dachte ich auch so, uh, ob das funktioniert, aber es funktioniert tatsächlich.
Und es kommt auch noch Strom durch.
Also ich suche auch so etwas Ähnliches.
Ich möchte gerne meine Monitore umschalten
mit so einem Switch.
Und zwar einmal auf eine Workstation
und einmal auf meinen normalen Rechner.
So eine KVM-Switch?
Ja, genau, eine KVM-Switch.
Und ich habe mich dann gefragt,
ob es da was Vernünftiges für gibt.
Weil ich hätte gerne auch die Auflösung der Monitore
und mit Switch immer hin und her geschaltet
zwischen allen Setups.
Das finde ich cool.
Aber ich habe noch keine Ahnung, was es da gibt.
Falls ihr da irgendjemanden kennt
oder einen guten Tipp habt,
her damit, ich freue mich drüber.
Das schaffe ich mir an und probiere das mal aus.
Ansonsten
habe ich nichts mehr. Johannes, hast du eine News?
Eine Neuigkeit? Nee, ich bin immer noch im WLAN.
Ich habe kein Kabel.
Du bist tatsächlich im WLAN bei dir im Haus?
Ja, das geht ja nicht anders.
Das ist zu weit weg.
Rohrmaschine? Ja, nicht in einem
Miethaus.
Und ich habe schon lange
so ein relativ altes
Lenovo-Dock. Das gehört auch
gar nicht zu meinem Rechner, sondern das habe ich einfach mal irgendwo
gekriegt für, keine Ahnung, 50 Euro oder so.
Ein Dock ist total gut.
Da ist einfach alles eingesteckt. Tastatur eingesteckt,
Maus eingesteckt, Monitore eingesteckt,
Storage ist auch dran.
Das ist total gut. Und du sitzt diesmal auf einem
anderen Stuhl und auf einem anderen Schreibtisch,
vor einem anderen Schreibtisch in deinem Büro.
Naja, nee, ich habe ja zwei
Arbeitsplätze in meinem Büro.
Der andere Arbeitsplatz.
Der ist ja praktikant nicht zu Hause, na gut.
Es gibt den
mobilen Arbeitsplatz und den immobilen
Arbeitsplatz und das ist jetzt der fest installierte
mit den großen Monitoren.
Okay, okay.
Ja, cool.
Dann würde ich sagen, von mir aus
kann man jetzt tatsächlich das Thema
Ich bin absolut begeistert,
das ist eine Weltpremiere hier heute.
Liebe Hörerinnen und Hörer, hört zu,
ihr wisst genau, was euch jetzt erwartet.
Weltpremiere Dango Async 3.1.
Ja, also genau.
Ich habe direkt mal eine Frage.
Ja, was ist denn der Async?
Muss ich irgendwas beachten,
wenn ich jetzt von 3.0 auf 3.1 upgrade?
Muss ich dann irgendwas machen
oder geht es dann auch noch alles?
Das geht alles genauso wie vorher auch.
Wichtigste Frage direkt geklärt.
Okay, also erstmal nochmal so vielleicht ganz kurz
so zum Frame, zum Rahmen, worum es eigentlich geht.
Was Async dann überhaupt bedeutet
und was man jetzt damit machen kann,
was vorher schon so ging, so diese Geschichte
und wofür man das eigentlich braucht.
Also womit wollt ihr denn anfangen?
Vielleicht, was das ist, Async überhaupt?
Und ja, dann kommt man vielleicht darauf,
warum man das vielleicht haben wollen
möchte oder vielleicht auch gar nicht braucht.
Das ist gleich eine schwierige
Frage am Anfang.
Also ich glaube, ich würde tatsächlich mit der
Motivation starten, weil sonst
wird das direkt so trocken und alle Leute
schalten sofort auf Durchzug und
wenn man so zumindest
weiß, dass es irgendwie vielleicht nicht so
super unwichtig ist und dass tatsächlich
interessante Dinge damit gehen, dann
vielleicht hält man ein bisschen länger durch.
Also du weißt schon, dass da Eve Online steht und das ist
gleich sonst einen Exkurs von mir zu EVE Online.
Ja, genau, das wäre
interessant.
Aber die sind doch noch auf 2.7.
Die kriegen ja doch die ganzen Sachen gar nicht mit.
Ja, ja, aber es gibt
wahrscheinlich Gründe, warum das so ist.
Also okay, ich fange einfach mal so an.
Das ist der Grund.
EVE Online hat von Anfang an gesagt,
wir haben, keine Ahnung, 15 Millionen Codezeilen
in unserem Server, wir fangen jetzt nicht an, die auf Python 3.
Also genau, EVE Online
basiert viel auf Python, falls ihr das noch nicht gehört habt.
Ja, genau. Und soweit ich weiß, ich weiß nicht, ob das immer noch so ist, aber soweit ich das gehört habe, auch auf Stackless Python.
Oh ja, das ist interessant. Da umgehen Sie ja gleich viele von den Dingen, weshalb man Async überhaupt braucht.
Genau, also beziehungsweise zu der Zeit, wo Sie das gemacht haben, gab es das halt einfach noch nicht.
Und Stackless Python war halt eine Lösung für die Probleme, die sich da gegeben haben.
Und ich meine, gut, wir können auch einfach direkt so einsteigen, weil das ist ja auch eine gute Motivation, warum braucht man sowas überhaupt?
Und was die wohl können, also hieß es jedenfalls,
ist, dass da das alles in Stackless-Python
halt auch so Userland-Threads oder Green-Threads
oder wie auch immer man die nennt, sind.
Stackless-Python, du brauchst keinen Execution-Stack
dafür im Betriebssystem.
Was Stackless-Python kann, ist, du kannst diese Threads picklen.
Ja, vor allem kannst du mehr als einen ausführen, oder?
Ja, ja, ja, das auch.
Das hat auch keinen Global Interpreter-Log, das heißt, du kannst
einfach...
Jetzt gerade wieder die ganze Bagage
mit dem Grammisch-Collector in den Müll.
Moment! Stopp, stopp, stopp,
da sind wir doch noch nicht.
Also, ich wollte
eigentlich nur mal kurz, warum man das eigentlich machen will,
was das Coole daran ist.
Dadurch, dass diese Threads, also wenn ich jetzt zum Beispiel
halt ein Ding, ich habe keine Ahnung,
wie die EVE Online funktioniert, ja, ich kenne das nicht gar nicht,
aber ich glaube, es geht irgendwie um Raumschiffe und so,
die da irgendwie im Weltraum rumfliegen.
Excel in Space.
Gut, wem es Spaß macht, aber
naja.
Und du hast jetzt irgendwie einen Thread, der jetzt so ein Raumschiff
simuliert, das da so richtig gegenfliegt.
Dann kannst du halt das Ding
pickeln, in eine Datenbank schreiben,
irgendwo anders wieder
auspacken und weiter ausführen.
Ja, das ist eine sogenannte
Continuation, wäre mal
die akademische Fachliteratur.
Ah, okay, gut.
Und das ist natürlich, wenn man ein
Riesenuniversum hat, vielleicht eine ganz gute Sache,
wenn man das machen kann, weil eventuell
will man halt nicht alles immer laufen haben,
sondern möchte halt auch
Teile von dem Universum, das man simuliert,
da irgendwie auch einfach mal
einfrieren und in eine Datenbank
schreiben und erst dann wieder auftauen, wenn man es
tatsächlich benötigt, damit man nicht immer alles
gleichzeitig ausführen muss oder so.
Wäre eine gute Idee für Zeitreisen.
Aber wir wollten über die Motivationen
nochmal dann doch vielleicht kurz, lass das doch mal kurz
heute ausnahmsweise strukturierter angehen.
Und dann, wir gehen auch versprochen wieder zu
EVE Online zurück.
Ja, also genau, die Frage ist halt sozusagen,
ob nicht es valide Use Cases gibt für so sehr,
das deutsche Wort ist so ein bisschen doof,
aber ich weiß auch nicht, ob man da ein besseres finden kann,
nebenläufige, also massiv nebenläufige Programme.
Also man braucht halt viel Concurrency.
Also es gibt Probleme, da hat man halt einfach ganz viel Concurrency.
Und die Frage wäre halt, muss man, wenn man so ein Problem hat, damit umgehen zu können, die Sprache wechseln oder nicht?
Das ist sozusagen, also diese, ich würde sagen, das zentrale, ich habe mir ein paar Sachen angeguckt und das zentrale Ding, das hat auch Tom Christie quasi in einem Vortrag auf der DjangoCon 2019, als er irgendwie einen, den er da gehalten hat, so gesagt.
Also es gibt da diverse Geschichten in Go,
es gibt diverse Geschichten in Node.js oder Rust
oder Erlang, Erlang ist auch ziemlich en vogue gerade
und die Frage wäre halt, wenn man jetzt so einen Use Case hat,
bedeutet das, dass man die Programmiersprache wechseln muss
und dann halt Erlang machen muss
oder halt kann man das auch in Python machen?
Eigentlich kann man das auch in Python machen,
ist jetzt sozusagen dafür die Infrastruktur
noch nicht so ausgeprägt wie in anderen Sprachen,
aber so prinzipiell geht das schon
und man könnte jetzt sagen, na gut,
das hat ein bisschen lange gedauert, also die Geschichte von
Async in Python ist wahnsinnig lang,
aber in letzter Zeit wird es halt
sehr interessant. Zum Beispiel, wenn man jetzt Django als Beispiel
nimmt, dann geht das jetzt gerade erst so
richtig. Und der Grund dafür ist,
dass eigentlich will man
die Syntax dafür haben, also
für Kuroutinen,
und die ist erst seit 3.5 so richtig in der
Sprache. Das heißt, vor 3.5 ist sowieso
schwierig. Und
Django hat mit Version
1.11 noch Python 2 supported.
Dann geht es auch nicht.
Das kann man einfach vergessen.
Und mit Django, glaube ich, 2.1, 2.2 weiß ich gar nicht mehr,
aber noch Python 3.4.
Und mit 3.4 geht es auch nicht.
Das heißt, bis vor kurzem konnte Django das gar nicht
mit der nativen Syntax machen,
weil Python-Versionen supportet wurden,
bei denen das einfach nicht geht.
Und jetzt ist es halt sozusagen alt und abgehangen genug,
dass sozusagen nur noch Python-Versionen unterstützt werden,
mit denen man das dann tatsächlich nativ machen kann.
Und jetzt kann man halt anfangen, das umzustellen.
Beziehungsweise die Arbeiten daran sind ja jetzt auch schon was älter,
aber jetzt ist es halt so weit, dass es tatsächlich mal in einer
verwendbaren, für User verwendbaren Form halt tatsächlich in Django ankommt.
Und wenn man sich sowas überlegt,
also was ich zum Beispiel mir angeguckt habe,
Erlang ist ja relativ irgendwo gerade,
beziehungsweise halt so ein Dialekt,
der oft dann so für Web-Entwicklungsgeschichten benutzt wird, Elixier.
Und da gibt es auch so ein Web-Framework Phoenix zum Beispiel,
Und da kann man auch mal sich angucken,
so Phoenix Elixier,
Live View, solche Sachen.
Und das sieht alles schon sehr beeindruckend aus
und ist auch sehr nett.
Und die Frage wäre halt, kann man sowas in Django
und Python auch machen? Und die Antwort ist eigentlich
ja. Eigentlich gibt es nichts, was einen davon prinzipiell
abhält.
Außer, dass es halt nicht, dass noch nicht so
unterstützt wird in den Frameworks und so. Aber
prinzipiell geht das schon.
Was macht das denn jetzt so schön?
Ja.
Ähm, keine Ahnung, habt ihr noch was oder wegen Motivation oder was? Ich überlege gerade, ob ich jetzt schon ausreichend motiviert habe.
Ja, da fehlt noch ein kleines bisschen vielleicht. Warum man das vielleicht macht, könnte man bei der Motivation direkt sagen, oder? Also was für Problemfälle gibt es denn, die man jetzt…
Ja, es gibt ja schon immer, also ich meine, es gibt ja schon immer Anstrengungen, Sachen zu parallelisieren und da gibt es auch schon ganz alte Sachen.
Nur damals war es halt, damals, ja, also vor zehn Jahren war es halt noch so, dass Computer zwei Cores hatten oder vier Cores und da ist es nicht so wild, wenn du nur einen benutzt.
Aber heutzutage ist es ja relativ leicht, gerade im Serverbereich, Sachen zu kriegen, die 64 oder 128 Cores haben oder noch mehr, wenn man das unbedingt haben möchte.
Oder wenn man auf Grafikkarten geht, kriegt man direkt
in die Tausenden von Cores.
Deshalb ist das, man darf da
nicht so viel Python verdammen, weil das
einfach vor zehn Jahren noch kein Problem war.
Ja, Moment, Moment, aber das ist jetzt, glaube ich,
ein anderes Problem, oder? Also, oder aus
meiner Perspektive ist es ein anderes.
Generell die Nebenläufigkeit,
die man da jetzt braucht.
Aber das braucht man, das haben die anderen auch nicht.
Das haben die anderen auch nicht. Also, das kriegst du auch
auf Node.js nicht hin.
Das mag sein, dass das mit Node.js nicht
nicht unbedingt hinkriegst, aber mit C
und Erlang und Rust und so weiter kriegst du die Sachen
schon hin. Und Go auch.
Ja, gut.
Die nutzen schon alle Cores aus.
Ja, aber da
weiß ich gar nicht, ob man das unbedingt braucht.
Da würde ich jetzt denken,
warum? Doch, also ich glaube,
für mich ist das schon eine Motivation,
mehr Cores ausnutzen zu können.
Geht zwar nicht mit
Async, das weiß ich, aber
ja.
Generell, der Trend geht dazu, mehr Sachen gleichzeitig zu machen, um es mal so auszudrücken. Und dafür braucht man halt irgendeine Syntax. Und klar, es gibt die ganzen Sachen, die man früher machen konnte. Da gibt es die coolen Message-Parsing-Interfaces und die coolen, was weiß ich, verteiltes Rechnen-Ansätze und dann gibt es Threads und Multiprocessing und so weiter.
Aber die
haben halt alle ihre Nachteile und die haben halt alle
ihre, sagen wir mal,
Schwierigkeiten.
Und gerade wenn man
anfängt mit Threads zu arbeiten in Python,
merkt man halt sehr schnell, dass das von der Geschwindigkeit her
überhaupt gar nichts bringt.
Also ist die Frage, was man
mit Schwierigkeiten meint, ja,
wenn es um
quasi wie schnell kann man
Dinge machen geht, dann
bringt einem das nichts, sondern
macht es einfach langsam.
Und auch, wie viele Sachen gleichzeitig kann ich machen.
Wir helfen einem
im Verhältnis in Python ja erstmal gar nichts.
Ja, wobei, da würde ich direkt
unterscheiden zwischen Sachen
parallel machen, das heißt,
und Sachen concurrent,
und daneben läufig, ja, weiß nicht, ob das eine gute Übersetzung
ist, könnte man nicht.
Die deutschen Worte sind da total blöd.
Weil parallel geht
halt in Python nicht, aber ich glaube auch nicht, dass
das das Problem ist.
Oder geht noch nicht.
Da gibt es verschiedene Workloads, glaube ich, die da
die du da bedenken musst.
Also Multi-Processing ist parallel?
Wenn du in Nampai bist, dann hast du ja schon Parallelität.
Mit Nampai kriegst du die Cores schon alle voll.
Ja, ja, klar, genau.
Insofern würde ich sagen,
das ist auch nicht so ein Problem.
Vielleicht muss man erst noch erklären,
was Parallelität und Nebenläufigkeit sind.
Ja, bitte, bitte.
Einmal kurz da einschränken.
Ja, aber ist jetzt Multi-Processing
nicht sowas wie parallel?
Ja, Multi-Processing ist parallel,
aber auch das kannst du nur machen,
wenn du wenig Kommunikation hast,
weil du da eben zwischen Prozessen kommunizieren musst
und das ist langsam.
Das ist generell die Krankheit, die du hast,
wenn du solche Message-Parsing-Sachen machst.
Das hatten wir ja früher auch schon gehabt.
Als ich studiert habe, hatten wir einen großen Cluster,
der hatte 16 Prozessoren an der Universität.
Und das waren halt unterschiedlich, es waren halt 16 Computer,
die mit einem schnellen Netzwerk verbunden waren.
Aber je weniger Nachrichten du schicken konntest,
schicken musstest, umso schneller war das dann halt.
Das heißt, im Wesentlichen warst du da gar nicht
die CPU gedrosselt,
sondern eben durchs Netzwerk.
Ja, ja, gut.
So ein bisschen ist es bei Multiprocessing ja auch.
Je weniger Nachrichten du schicken musst, umso
besser. Aber da musst du überhaupt gar keine schicken.
Irgendwie, dass man sagt, man hat so
eine gemeinsame Verwaltung. Genau, es gibt Chat-Memory.
Kannst du einfach wenden. Musst du gar keine Nachrichten schicken.
Cool, sowas gibt es schon? Ja, ja. Das ist auch eingebaut.
Seit Python 3.8 ist das drin.
Also kannst du sagen, hier irgendwie, ja.
Umso besser.
Aber dann hast du trotzdem noch
irgendwelche Locking-Mechanismen, die dir da
wo wir halt warten mussten.
Aber wenn du CPU-Bauern bist, ist das alles nicht mehr schlimm.
Also das ist alles, also ich würde sagen,
wenn du Dinge einfach,
wenn du jetzt irgendwie Number-Crunch-Geschichten machst,
da alle Cores zu verwenden,
ist in Python überhaupt kein Problem.
Das geht super. Das ist tatsächlich einer
der beliebtesten Anwendungsfälle für Python.
Also ich würde sagen, Data Science,
da ist Python wahrscheinlich die Sprache Nummer 1 gerade.
Und das ist ja
hauptsächlich so ein Zeugs. Und da geht das super.
Da werden immer alle Cores benutzt, gar kein Problem.
Ja, klar. Im Wesentlichen ist der Trick halt daran, dass die aus Python rausgehen, die Bibliotheken, und dass die das halt in C machen.
Ja, oder du kannst halt auch so Dinge machen, nee, nee, nicht nur. Also du kannst auch pure Python-Funktionen parallelisieren.
Also mit REST geht das, auch mit mehreren Maschinen hinweg.
Ach so, ja, okay.
Aber das ist, also ich habe hier gerade die …
Also das ist jedenfalls Parallelität.
Ja, genau, das ist Parallelität.
Man macht Berechnungen auf mehreren Prozessoren und die sind gleichzeitig im Wesentlichen.
Und es spielt keine Rolle, ob es die gleiche Berechnung ist oder
eine andere Berechnung. In den meisten Fällen
werden es ja die gleichen Berechnungen sein.
Und wenn er zuerst fertig ist,
dann schreibe ich. Auf allen Zeilen dieser
Tabelle möchte ich jetzt ausgerechnet haben,
was die Summe ist. Genau, genau.
Also ich habe
hier die Definition von
Rob Pike, von dem
jenigen, der sich da
mal ausgedacht hat. Und der sagt halt
Concurrency is about dealing with
lots of things at once.
Parallelism is about doing lots of things
at once. Not the same, but
related. One is about structure,
one is about execution.
Concurrency provides a way to structure
a solution to solve a problem that may
but may not necessarily
be parallelizable.
Ja, das sagt er erst mal.
Ich dachte, das hätte ich gerade.
Nee, das
fand ich jetzt auch nicht arg erhellend.
Verdammt, na gut.
Ja, Parallelität ist halt
Sachen gleichzeitig machen
und Concurrency ist verschiedene Sachen
machen. Das ist so, wie es in meinem
Kopf ist. Ja, eine Erklärung, die ich mal gehört
habe, vielleicht ist die besser,
vielleicht einfach mal ein paar durchprobieren,
ist, dass halt sozusagen
ein Bartender
kann irgendwie viele Kunden
concurrent
behandeln, sozusagen, oder wenn ein Bartender
viele Kunden hat,
die er mit
Drinks beschickt, dann
ist das irgendwie Concurrency, aber
wenn du mehrere Drinks gleichzeitig machen willst, brauchst du mehrere
Bartender. Da reicht einer nicht.
Und das wäre dann Parallelität, sozusagen.
Ja, also mehr
Arme für den Barkeeper.
In meinem Kopf
geht es
bei mir ganz viel um das Wort gleichzeitig.
Parallelität heißt
du machst mehrere Sachen gleichzeitig.
Und
Nebenläufigkeit oder Concurrency heißt,
du machst mehrere Sachen
nebeneinander her. Also nicht an einem
abschließenden Schritt erstmal den einen Drink mixen,
sondern fünf Gläser hinstellen und jedes Mal
einmal ein bisschen Zitrone rein und dann ein bisschen
Drink. Genau, genau. Also du hast
fünf Drinks, die du zubereiten musst und du machst
halt die Schritte von denen und du machst erstmal was
an dem Drink eins, dann machst du was an dem Drink zwei,
dann machst du was an dem Drink drei.
Die Gesamtzeit ist
dann ja genau dieselbe, als würdest du fünf einzeln
machen, nur du hast halt dann fünf
gleichzeitig rausgeschickt und alle haben quasi
die Zeit gewartet, anstatt dass du jeweils erstmal
den ersten, den zweiten, den dritten, den vierten, den fünften
Genau, also du machst eventuell die
Latenz geringer. Du kannst
schon mal die Bestellung des Nächsten
annehmen, während ein Drink noch
in Bearbeitung ist. Ja, aber dann doch nur die Durchführung.
Ja, du kannst halt den Nächsten bearbeiten, während einer noch, weiß ich nicht,
in einem irgendeine fürchterliche chemische
Reaktion läuft, die halt eine Zeit lang braucht
und du wartest halt jetzt nicht stumpf davor ab.
Oder du wartest auf den Assistenten.
Ja, aber der Erste, der sonst
seinen Drink sofort bekommen hätte, weil es erst in der Schlange stand,
der muss jetzt länger warten, weil er die anderen Drinks
auch nicht hat. Potenziell ja.
Aber guck mal, wenn da gerade kein Eis da ist,
dann kannst du ja einen anderen Drink
machen, während du aufs Eis wartest oder während dir
jemand was aus dem Lager holt.
Das merkt der erste Kunde überhaupt
gar nicht, weil der muss so oder so drauf warten,
bis sein Eis da ist.
Ja, aber nur dann kannst du was anderes machen.
Mit deinen Tasks.
Ja, genau, wenn du Wartezeiten hast.
Und dann bemerkt der erste
Kunde gar nichts. Dann hast du automatisch
weniger Latenz und
mehr Durchsatz, weil du Wartezeiten
nutzen kannst. Und das ist ja eine der großen
Allüren dieser
ganzen Geschichte, dass du sagst, okay, ich muss jetzt
eh auf eine Datenbank warten oder auf
die Dateien. Ja, also sobald zwei Leute
da arbeiten, also nicht nur den Barkeeper,
sondern auch noch die Küche und du möchtest immer einen Drink mit
Essen servieren oder sowas. Und solange das Essen noch nicht fertig ist,
dann kannst du alle anderen Drinks schon fertig
bereiten. Ja, genau. Wenn du Abhängigkeiten
hast oder wenn du Wartezeiten hast, die kannst du
überbrücken, indem du da was anderes machst. Und das ist
Concurrency. Du machst nie Sachen gleichzeitig.
Du hast, der Bartender kann nie
mehrere Sachen gleichzeitig machen.
Dem wachsen keine fünf oder sechs Arme.
Genau, der hat halt nur einen
Prozessor.
Aber der kann mehrere Drinks gleichzeitig zubereiten.
Das heißt nicht, dass er überall gleichzeitig was reinschüttet,
aber das heißt halt, dass die alle
zu einem gleichen Zeitraum in Bearbeitung
sind. Genau wie der Jochen sagt, wenn
du fünfmal so viele Drinks
machen willst, brauchst du halt mehr Bartender.
Und die sind dann auch erstmal unabhängig
voneinander. Es gibt jetzt leider keine
Simdi-Bartender, die
mehrere Sachen
identisch gleich machen können, dann
könntest du fünf identische Drinks
gleichzeitig zubereiten.
Da wüsste ich jetzt keine
Analogie in der
echten Welt.
Async ist jetzt Parallelität
oder Concurrency?
Ich würde sagen, dieses Problem Parallelität
ist, also dass du
beides gleichzeitig brauchst,
das wäre jetzt mal eine steile These,
ich meine, ich weiß jetzt auch wieder, wann wir das schon mal hatten
Und ich glaube, das war tatsächlich in der ersten Sendung, wo ich halt auch meinte, so eigentlich diesen Fall, dass man beides hat, dass man Concurrency braucht und Parallelität, den hat man fast nie.
Also, oder mir fällt es schwer, mir dafür einen Use Case auszudenken.
Die anderen Fälle hat man, dass man viel Concurrency braucht, hat man, dass man viel Parallelität braucht, hat man, aber beides zusammen.
Ja, also ich kann mir jetzt viele Sachen vorstellen.
Also wenn ich jetzt beispielsweise vorstelle, autonomes Fahren oder Sport oder sowas.
und gleichzeitig fahren bestimmte Menschen
übers Eis oder sowas.
Und da musst du prognostizieren,
was dann passiert. Das ist echt parallel
für jeden Einzelnen.
Ja, aber das ist nicht concurrent.
Du machst das Auto fahren gleichzeitig.
Nein, es fahren alle gleichzeitig und alle müssen gleichzeitig
darauf reagieren. Und du möchtest ja für alle
gleichzeitig irgendwie Werte haben.
Du möchtest dann das ganze Team.
Das verstehe ich nicht. Tut mir leid.
Also du hast mehrere Fahrzeuge.
Du hast so einen Rechner, auf den mehrere
Fahrzeuge fahren? Das verstehe ich nicht.
Genau, du hast die ganze Flotte, die du steuerst.
Ja, aber die sind ja unabhängig.
Also ich würde sagen, das ist ein Anwendungsfall,
den kenne ich so nicht. Aber du hast ein gegnerisches Team
und das ist halt nicht unter deiner Kontrolle und du möchtest
dann trotzdem alle deine Leute,
deren Informationen du dann halt gerade erst
live einlesen kannst,
dazu bringen, dass sie parallel
die Entscheidung treffen,
die vernünftig,
statistisch wahrscheinlich ja zu besseren
Ergebnissen funktionieren, irgendwie so.
Der Dominik überspringt
so die simplen Schritte.
selber fahren können müssen, der macht direkt
komplett. Ne, tut mir leid, das würde ich sagen,
das ist kein Newscase.
Vielleicht doch. Da wüsste ich jetzt auch nicht.
Ne, aber
wir können ja direkt mal zu einem
super guten Newscase zurückgehen und der heißt
EVE Online. Da sind ganz viele Spieler,
die gleichzeitig Sachen machen wollen
und du hast aber trotzdem die große
Statustabelle auf dem Server, die du die ganze Zeit
aktualisieren musst und das musst du parallel machen.
Also ich meine, die Lösung, die EVE Online
dafür hat, ist halt, dass sie es langsamer machen.
Habt ihr EVE Online mal gespielt?
Nee, nur ganz viel drüber gelesen.
Oh, ich habe es tatsächlich auch mal ausprobiert.
Ich muss gestehen, ich war nicht in den Gruppen.
So viel Zeit habe ich nicht.
Ja, das habe ich auch nicht geschafft.
Aber es gab tatsächlich tolle Schlachten.
Also man hat dann so Schlachten gehabt,
wo dann so 20.000, 30.000 Schiffe verloren gegangen sind.
Und man konnte da ein Business draus machen,
weil da konnte man die Schiffe kaufen.
Das war richtig Geld, was da vernichtet wurde.
Ich glaube, in der größten Schlacht
wurden mehrere Millionen Dollar an virtuellem Kapital vernichtet,
gleichzeitig, weil man irgendwelche Sprungtouren blockiert hat
mit riesigen Flotten an Schiffen
und alles in die Luft gesprengt hat,
was dann ja nie zu finden war.
Ja, das ist das Geschäftsmodell von EVE Online, oder?
Ja.
Du kannst virtuelle Güter kaufen und sie dann verbrennen.
Ja, und du kannst sogar tatsächlich aber in diesem Spiel
konntest du halt Echtgelddinger generieren,
die du halt verkauft hast.
Und wenn du halt ein Wirtschaftsunternehmen,
Imperium, in diesem Spiel aufgebaut hast.
Es gab eine Leute, ich glaube, die haben über 20.000 Dollar
oder sowas im Monat gemacht,
indem die für EVE Online Businesses gebaut haben,
die sie da durch die Dachen geschleust haben.
Und wenn du dann halt sowas gemacht hast,
wie einen Krieg zu organisieren zwischen den einzelnen Fraktionen,
die sich gegenseitig in die Luft sprengen
und das halt alles auf dieser spielerischen Karte,
ohne dass das jetzt reale Auswirkungen hätte, also außer
wirtschaftliche, für die Jungs, die da vor dem
Rechner saßen, dann war das
schon irgendwie sehr faszinierende Geschichte.
Aber guck mal, Jochen, das ist doch
ein perfektes Beispiel, oder? Du hast ganz viele
Spieler, die gleichzeitig Sachen machen wollen und
du musst aber diese Statustabelle,
das ist parallel. Ja, also ich würde sagen,
ich bin nicht
so der Spielexperte, insofern, keine Ahnung,
aber ich würde jetzt mal sagen, Spiele,
die sind alle nur concurrent, da brauchst
du nichts parallel. Wenn ich jetzt so gegenseitig
spiele, ein ganz klassisches Killerspiel,
Ja, und wir schießen beide gleichzeitig aufeinander.
Aber wo brauchen die denn, wo brauchen die Spiele
denn bitte CPU?
Die brauchen überhaupt gar keine CPU.
Die Spiele heutzutage
laufen nicht mehr auf dem Client, sondern die laufen komplett
auf dem Server. Ja, selbst wenn die komplett auf dem Server laufen,
wo brauchen die denn CPU?
Diese vorher genannte
Battle, die der Dominik genannt hat,
wo dann 30.000 Leute teilnehmen.
Der Trick an der Sache, warum das funktioniert,
ist, dass die den Timestamp runterdrehen.
Das heißt, in so einer Zone, wo viele
Leute gleichzeitig sind,
Die müssen auf einem Server sein, damit diese Zone kohärent ist. Wenn da zu viele Leute sind, dann tun die so, als ob die Zeit langsamer läuft, weil der Rechner ausgelastet ist.
Und wenn die diese Status-Updates parallel abarbeiten könnten auf einem Rechner, dann müssten sie das nicht machen. Die gehen ganz, ganz hart ans Limit, weil die Simulation auf dem Server passiert.
zum Teil passiert die Physik-Simulation
auf dem Server. Das ist im Wesentlichen
der Grund.
Man hört ganz oft, dass
so und so viele Millionen Leute gleichzeitig in Fortnite
sind. Aber das stimmt nicht. Es sind nur
höchstens 50 auf einer
Instanz. Jetzt
gab es so Events, wo 10 Millionen Leute
bei so einem Konzert dabei waren.
Das ist ein kleines bisschen gelungen. Das waren 250.000
Instanzen mit
jeweils maximal 50 Leuten, weil da
einfach die Auslastung,
da ist der Prozessor voll.
Und da ist Parallelität einfach ...
Okay.
Je mehr Parallelität du nutzen kannst,
umso höher kannst du diese Zahl setzen.
Und umso weniger Instanzen brauchst du.
Und das ist richtig, da ist Geld drin und da ist richtig ...
Okay, vielleicht weiß ich einfach noch nicht gut genug,
wie Spiele funktionieren,
dass ich mir gar nicht so richtig vorstellen kann,
warum die jetzt CPU brauchen.
Also die Frage ist halt, wo ist da der Flaschenhalt?
Ist der Flaschenhalt tatsächlich CPU?
Das ist dann irgendwie sowas wie Netzwerk.
Ich glaube eher Concurrency und Netzwerk, ja.
Da müsste man Peer-to-Peer vielleicht machen.
Das würde vielleicht schneller gehen,
wenn man das irgendwie über Peers verteilt,
als dass man irgendwie alles durch einen Hals schickt.
Bei allen Leuten irgendwie so ein bisschen was weitergeht.
Da gibt es sicher viele Flaschenhälse.
Ich glaube, da ist alles, das ist so ein blödes Problem.
Wenn du ein Problem gelöst hast, dann kommt direkt das Nächste.
Wenn du einen Kopf abgeschlagen hast,
wachsen direkt vier neuere.
Aber CPU ist da einfach einer der Faktoren.
Vielleicht ist es bei Spielen so.
Ich kann es noch nicht so richtig nachvollziehen, aber okay.
Also ich meine, mir fällt auch ein Beispiel ein,
und das sind halt Datenbanken.
Da hast du nämlich auch beides.
Da hast du halt sowohl I.O.,
du hast halt, weiß ich nicht, 30.000, 40.000 Requests pro Sekunde,
Und die machen alle CPU.
Die machen alle irgendwie
Geschichten in irgendwelchen
Biotrees irgendwie durchsuchen,
irgendwelche Indizes
abgleichen,
ja, Hashes ausrechnen. Und je mehr
du gleichzeitig machen kannst, umso besser.
Genau. Also an der Stelle würde ich sagen, also Datenbank-Server
und Python schreiben, vielleicht nicht die beste Idee, weil das
wird schwierig. Aber... Wie ist es mit
Videostreaming? Auch das ist sowas, wo...
Würde ich sagen, komplett concurrent. Da gibt es nichts,
was irgendwie CPU braucht. Nein, überhaupt nicht.
Na klar. Also außer du kodierst irgendwie
um, aber ansonsten. Ja, und zwar, und musst
du. Du musst die Sachen umkodieren.
Dann. Jeder, jeder,
jeder moderne Streaming-Dienst,
also wir sind jetzt hier auf Whereby,
aber wenn du auf BBB gehst oder auf
Zoom oder auf sonst was, die kodieren alles um.
Tatsächlich
machen die Größenskalierungen,
damit die Clients mit
unterschiedlichen Bitraten versorgen können.
Und das kannst du entweder auf dem Client machen, was
nicht super zuverlässig ist, weil die Clients
halt auch Mobilgeräte sein können.
Du machst auf dem Server und dann bist du ganz knallhart
Ja, aber da würde ich sagen, da bist du doch sowieso schon
da ist der Flaschenhals auch wieder woanders, weil
dadurch, dass du
dass die einzelnen Clients, die du
dran hast, so fett sind
macht es doch überhaupt nichts, wenn du pro Verbindung
dann halt was Fettes aufmachst, wie ein Prozess oder so
Ja klar, aber du hast auf jeden Fall
Parallelität, du musst auf jeden Fall
diese 8 Streams
Das ist auch bei dem Spiel, wenn du sagst, es gehen nur 50 Leute
auf eine Instanz oder es gehen nur 50 Streams
über einen Rechner, dann machst du halt für die
50 Prozesse auf, gar kein Problem, geht das auch mit
Ja klar, aber das ist dann schon Parallelität.
Also du machst schon viele Sachen gleichzeitig.
Ja, aber
ein Fall, nach dem ich suche, ist,
wo du ganz, ganz viel Concurrency hast,
so viel, dass du das mit Prozessen nicht erschlagen kannst,
weil es zu viele sind. Also sagen wir mal,
du hast 10.000 Verbindungen gleichzeitig.
Aber das kannst du ja bei einem Webserver locker mal haben.
Ja, natürlich, genau. Also du hast
10.000 gleichzeitig, die auch gleichzeitig aktiv sind.
Nicht nur einfach eine Verbindung, die rumliegt, sondern tatsächlich
aktiv, über die irgendwas drüber geht.
Wenn du das Problem hast,
plus irgendwie CPU, dann kannst du es vergessen.
kriegst du es mit Python nicht mehr hin, weil Prozesse kannst du dann
nicht mehr nehmen. Ich glaube, du hast das ausprobiert.
Hast du mal so eine Story erzählt auf deinem Mac und
hast Kernelpanik verursacht. Kann das sein?
Ja, das habe ich jetzt im Zug.
Aber das waren Threads tatsächlich, keine Prozesse.
Also mit Prozessen wird das gar nicht gehen. 10.000 Prozesse
ist nicht möglich. Aber
Threads sollten eigentlich möglich
sein.
Nicht auf dem Mac. Und ich habe es
tatsächlich dann auch mal auf einem anderen ausprobiert,
um auszuschließen, dass irgendwie meine Hardware leicht defekt
ist oder so. Nö, auf Catalina
macht das halt sofort Kernelpanik, wenn man 10.000
Threads aufmacht. Also die
Lüfter gehen kurz an und dann ist der Rechner aus.
Ich habe da tatsächlich auch einen Bug bei Apple
aufgemacht. Das geht ja so nicht.
Ja gut, aber ich meine, wenn man da in die
Ecken und Kanten geht. Also ich habe auch schon mal
mein Mac mit einem Programm abgeschützt, was nur
das Clipboard
ausgelesen hat.
Ja, es ist
ein großes Kartenhaus.
Ein großes Kartenhaus.
Ja, tatsächlich. Ich habe es dann
jetzt auch nochmal auf Linux probiert und so und da
geht es problemlos, gar kein Ding.
Ja gut, aber so eine Situation
wurde 10.000 Threads.
Also ich meine, das ist dieses
berühmte C10K-Problem.
Wie schaffst du es, einen Web-Server
zu machen, der 10.000 Clients
gleichzeitig benutzen, bedienen
kann? Und wenn du
das hinkriegst, ist es besser.
Weil dann hast du weniger Web-Server.
Aber dafür würde ich sagen, brauchst du eben keine CPU, sondern das ist rein
Concurrency und das geht
problemlos mit einem Prozess
und einer zu bringen. Aber ich finde
bestimmt irgendeine Workload, wo du noch was berechnen musst.
Wo du noch, keine Ahnung, Bilder skalieren musst.
Ich glaube auch. Ich glaube, dass es sowas tatsächlich gibt.
Aber es ist so einfach, dass man
sagt, also ich kenne das ja dann immer so,
dass Leute sagen, das ist ja gar keine richtige
Problemgespräche. Aber ich meine, wer hat solche Probleme?
Also ich hatte sowas
ehrlich gesagt noch nie.
Und ich habe schon eine Menge Zwergs gesehen.
Bei mir war es entweder
Vielleicht ist es einfach so,
ich glaube, da ist so ein bisschen
Selection Bias auch drin, oder?
Gut, kann auch sein, ja.
Klar, wir haben auch schon viele Sachen gesehen,
aber wir sind halt in Python unterwegs
und wir sehen nur solche Sachen, die es in Python gibt.
Ja, ja, ja, das mag sein.
Das kann durchaus, ja.
Ja gut, wie auch immer.
Wie auch immer, aber genau, diese Parallelität-Ding,
also wenn man beides braucht, ist halt schlecht.
Das ist nach wie vor nicht gut in Python.
Aber sagen wir mal so, dieser Concurrency-Use-Case,
für den es ja tatsächlich auch Anwendungen gibt
und ich meine, Node.js ist einer der Gründe,
warum Node.js so populär ist,
ist halt, dass es damit besser ging.
oder dafür halt besser benutzt wurde,
äh, besser benutzbar war, äh,
und, ähm, ja, äh.
Ja, auch ein besseres Programmiermodell
hat, oder? Also dieses,
ähm,
Promisers und Futures und so weiter, das,
ja, das ist alles schon sehr einfach.
Ja, aber das ist eigentlich alles, äh,
sozusagen, das gibt's halt in Python ja auch.
Ähm.
Ja. Was, was gibt's denn da in Python?
Gibt's schon, aber. Kannst du das kurz beschreiben?
Ja, also gut, okay.
Also wenn wir jetzt schon
im Grunde wissen, okay, wir wollen das
eigentlich schon haben und das ist schon cool und das kann ja
wohl nicht sein, dass ich jetzt Node.js lernen muss, nur
irgendwie, um immer noch
hip zu sein,
dann kann man sich ja,
genau, kann man so, okay, wie macht Node.js das denn
eigentlich, weil Node.js hat
die gleichen Beschränkungen im Grunde, ist sehr vergleichbar
zu Python, hat die gleichen Beschränkungen,
da gibt es auch in GIL,
ja, ganz genauso wie in Ruby on Rails
und sonst irgendwie in PHP
Die ganzen Skript-Sprachen machen das ja alle.
Die machen das alle so, weil es halt auch sinnvoll ist.
Ja, und weil es halt
auch single-threaded die Performance, also wenn du
kein Multiprocessing brauchst, also wenn
du keine Parallelität brauchst und
keine Concurrency, dann ist es halt das Schnellste.
Ja, genau. Und was
Node.js macht, ist halt,
sie haben halt eine Event-Loop und
ja,
dann kann man halt
sozusagen
Callbacks auf dieser Event-Loop, oder sagen wir so,
das ist halt das, was ganz früher schon immer,
ich glaube, das ist schon immer möglich, irgendwie, man kann halt Callbacks
auf dieser Event-Loop registrieren, oder?
Ja, Callbacks sind ja was Schreckliches,
das ist doch die Callback-Hell. Genau, ja.
Gar keine richtige, gar keine lineare
Programmierung mehr. Hast du was gesagt? Hatte ich irgendwas gesagt?
Vielleicht gab es da irgendjemand, der hat was gesagt, der wollte,
er wartet noch auf irgendwas. Wie heißt denn das? Wie muss ich
dann da fragen, wenn ich das wissen will? Ach, Moment,
da steht jemand, der hat da rumgegangen, ach nee, da war noch
jemand anders. Ach, Moment, da war noch jemand,
der hat aber was gesagt, was dann irgendwie, ach, Callback,
ach so, da hinten, ach nee, da unten, ah, oh.
kriegst du ja immer. Das Problem ist, dass dein Programm
dann auch so aussieht, weil du die Callbacks
quasi in der falschen Reihenfolge definieren
musst. Du kannst nicht sagen, erst
A, dann B, dann C, sondern du musst
erst sagen, erst A und wenn es erfolgreich ist,
dann B, ansonsten C und wenn
B erfolgreich ist, dann zwischendurch
D und E und dann hast du A, B,
E, F und C
kommt dann irgendwo ganz anders. Das heißt, du hast dein
Programm nicht mehr, kannst es nicht mehr
von oben nach unten lesen,
sondern du musst es so gemixt
lesen und das ist ganz, ganz, ganz blöd
zu programmieren. Und deshalb hat JavaScript dann
irgendwann diese Promises und Futures eingeführt,
wo du einfach sagen kannst,
da kommt jetzt was zurück,
was irgendwann
fertig ist und
sobald du es benutzt, musst du halt warten.
Ja, kann man,
in Python
gibt es das halt quasi ganz genauso.
Also seit 3.2
gibt es Concurrent
Futures.
Ich weiß nicht, ob sich
JavaScript, das auch so das Promises-Konzept
da so ein bisschen abgeguckt hat. Also Python hat sich das
abgeguckt aus der Java-Welt tatsächlich,
wo es dieses Future-Konzept wohl schon länger gibt.
Aber in Java nimmt man doch viel eher Threads, oder?
Ja, aber man kann auch
das machen.
Genau, also aber
sagen wir so, wenn wir jetzt schon bei den Callbacks sind,
oder bei dieser
Art, das kann man halt in Python
im Grunde auch so machen.
Ja, klar.
Ja, also
das ist auch in dem Async-Teil, also
sagen wir mal so, man muss das wahrscheinlich alles
so ein bisschen voneinander unterscheiden, es gibt halt
ein riesiges Glossar machen. Ja, genau,
wie das unten drunter aussieht, was man unten drunter für
einen Mechanismus verwendet, um halt
Concurrency zu erreichen und
was man dann für Abstraktionen darüber verwendet,
weil tatsächlich in Async.io jetzt
sozusagen die aktuell
in der Standardbibliothek
befindliche Lösung für diese
Concurrency-Geschichte ist halt
Ja, sogar in der Sprache, oder? Ist nicht
eine Bibliothek, sondern ist richtig in die Sprache integriert
mit Schlüsselwörtern. Ja, aber
das ist auch eine
gute Sache, das ist voneinander getrennt. Also,
was in der Sprache tatsächlich drin ist, ist halt
sind halt Async-Funktionen.
Also, die man halt mit Async-Dev
Async-Dev, genau, und Await
mit diesen Schlüsselwörtern
kann man da operieren, aber
in der Sprache ist nur definiert,
dass diese Geschichten dann, wenn du sie
aufrufst, halt eine Co-Routine zurückgeben.
Es ist nicht gesagt, wie
das jetzt alles sonst funktionieren muss. Der Rest ist
halt... Ja, okay, klar, die Event-Loop
und so weiter. Du kannst nämlich, genau, du kannst halt
Async-Dev und Await
auch in Trio verwenden. Und Trio verwendet ein ganz anderes
Modell unten drunter als jetzt Async-IO.
Trio, das
ist eine Implementierung
sowas Ähnliches wie Async-IO,
bloß mit einer
etwas moderneren, etwas anderen Zielsetzung.
Also es gibt diverse. Es gibt Async-IO,
ist in der Standard-Bibliothek. Es gibt
Curio, das ist das
von David Beasley.
Ist halt sozusagen erst ab Python 3.7
und irgendwie so ein bisschen
advancer.
Und dann gibt es nochmal die advancedere
Version von Nathaniel Smith
im Trio.
Und das Ding macht
im Grunde sowas ähnliches, aber halt
anders. Also die Art, wie man es
programmiert, ist halt anders.
Und benutzt aber Async-Def kann man
in all diesen Dingern verwenden, weil
das halt nur sagt, okay, wenn ich
eine Async-Funktion habe, dann
gibt die halt eine Core-Routine zurück.
Und ich kann jetzt damit irgendwas machen. Aber wie das
Programmiermodell aussieht, was ich dann mit diesen
Co-Routinen mache. Das ist ja demjenigen, der
das sozusagen, dieses Framework implementiert,
überlassen. Und da gibt es unterschiedliche
Ansätze. Und im Grunde
Trio ist
so ein bisschen das zu Ende gedacht, dass das halt so
ein Problem ist. Also das wurde ja auch schon angedeutet
mit dieser Callback-Hell-Geschichte. Also
das grundsätzliche Problem, was
auch der Autor von Trio da identifiziert
hat, also ich packe da auch mal
einen Artikel, wo man das in Detail nachlesen
kann in die Shownotes, dass er sagt,
das ist alles, also die Problematik
großer Teil der Probleme, die wir hier sehen, sind
die gleichen Probleme, die Leute
früher mit GoTo hatten.
Oder ich sag, das ist halt eine sehr gute
Analogie dafür. Wir sind in der Assembler-Welt
angekommen, wenn wir über GoTo sprechen.
Ja, nee, nicht ganz Assembler.
Ganz viele Sprachen, die GoTo haben.
Ja.
Also,
das Problem bei GoTo ist halt irgendwie,
dass es dir,
was das unmöglich macht,
ist halt lokal über Code nachzudenken.
Weil du weißt halt nicht, also er hat
dann halt so ein schönes Diagramm, wo man halt
er macht halt immer, er geht von einem
Go-To zu einer Zeile und dann, er macht das halt
immer weiter, bis du halt siehst, das ist ein riesiges
Spaghetti-Kneuel. Das heißt, du
weißt halt nie genau,
wie du eigentlich hingekommen
bist und wo es hingeht.
Und zum Beispiel, du kannst halt keine
Tracebacks werfen, weil du weißt überhaupt nicht, wo du herkommst
eigentlich. Und
das ist halt relativ schrecklich,
du musst halt dann das Programm
immer komplett verstehen. Ansonsten
kannst du nicht sagen, was da gerade passiert
weil es keine lokalen Blöcke gibt, wo man sagt,
okay, ich habe jetzt ungefähr verstanden, was das Ding tut.
Das muss ich jetzt nicht noch,
also ich brauche nur zu wissen, wie die Abstraktion davon ist.
Und das reicht mir, um damit arbeiten zu können.
Zum Beispiel irgendwie sowas wie Print Hello World.
Print macht intern was relativ Kompliziertes.
Das macht irgendwie Syscalls,
das macht irgendwie alle möglichen komischen Dinge,
die halt dann so zu tun sind,
wenn dann was auf der Konsole erscheinen soll.
Aber das muss man
alles nicht wissen, sondern man ruft das einfach auf
und das geht. Und Funktionen sind halt
super, weil genau die brauchst du ja
eigentlich nur zu merken, was das Ding tut, aber wie das
intern funktioniert, das muss einen nicht mehr interessieren.
Ist auch die gleiche Idee bei Klassen und so weiter.
Und mit Gotoh funktioniert
das halt nicht, weil du nicht sagen kannst,
okay, ich weiß jetzt, was hier
passiert und muss mir darüber keine Gedanken mehr machen,
weil es kann halt passieren,
dass dein Code nicht wieder dahin zurückkommt,
wo du es, also es gibt nicht so einen Aufruf, der wieder
zurückkommt, sondern das kann
verschwinden und ist dann halt irgendwie weg und es passiert was völlig
anderes. Und das ist halt schlecht, wenn
das so ist, weil dann kann man nicht mehr lokal
über Code nachdenken. Und
er meinte halt so, ja gut, also in den
Ende der 60er, 74er
Dijkstra und so, da gibt es halt den berühmten Artikel,
die haben sich da Gedanken gemacht und
deren Vorschlag war halt, ja,
Gotoh rauswerfen,
verbannen, irgendwie ächten
und stattdessen sowas verwenden wie
Funktionen und Blöcke und so.
Und das hat sich durchgesetzt
und auch lustig, die
Gegenargumente damals und auch
Knut hat zum Beispiel gesagt, oh nö, ich
finde Kutu eigentlich ganz gut.
Auch sehr interessant.
Knut? Ja, Donald Knut.
Ah, war das nicht der, der
sowas gesagt hat wie Premature
Optimization is the root of all evil?
Genau, genau der.
Aber dieses Zitat ist mit
sehr viel Vorsicht zu genießen. Er hat auch gesagt, wenn man
drei Prozent rausholen kann, dann ist es nicht mehr
Premature.
Ja, ja, ach ja, andere Zeiten.
Ja, jedenfalls.
Genau, der war da auch nicht unbedingt so totaler Fan von Gotoh Rausschmeißen,
weil so eines der Argumente war halt so,
ja, das bedeutet ja, wir müssen ganz anders programmieren lernen.
Wir haben jetzt über Jahre irgendwie,
haben wir uns auf ein Level begeben,
dass wir damit irgendwie jetzt klarkommen
und haben uns so Methoden angewöhnt, wie man damit umgeht.
Und wenn wir das jetzt so ändern,
dann müssen wir im Grunde nochmal neu programmieren lernen.
Und ja, das ist wohl so.
Und vielleicht wird es dann sogar langsamer,
weil eben diese Funktionsaufrufe
und diese ganzen Strukturmechanismen,
die verbrauchen ja auch Rechenzeit.
Ja, natürlich.
Und Speicherplatz.
Genau.
Und wenn du nochmal 3% irgendwo rausholen kannst,
dann kannst du das auch machen.
Und wenn der Mainframe super teuer ist
und Arbeitskraft super billig,
dann macht es vielleicht sogar Sinn.
Aber heute vielleicht nicht.
Ja, das ist halt,
wir stehen auf den Schultern von Riesen.
Wir haben heute genügend Prozessoren,
Wir haben genügend Megahertz,
dass wir uns das leisten können.
Ja, und im Grunde,
er sagt halt, ja,
also bei Concurrent
Programmierung
hat man im Grunde in gewisser Weise das gleiche Modell
und er sagt zum Beispiel, Futures
findet er ganz schrecklich, weil
die im Grunde das gleiche Problem haben
wie Gotoh, weil du kriegst halt was zurück.
Also du rufst eine Funktion auf, du kriegst was
zurück, aber du bist ja
gar nicht, das ist ja gar nicht linear zurück.
Dein Code geht ja nicht linear weiter.
sondern irgendwo anders passiert
irgendwas, das aber
durchaus Auswirkungen darauf haben kann,
was später in dem Code, der dann
jetzt sozusagen von dir aus gesehen weiterläuft,
darauf Auswirkungen
hat. Das heißt, du musst wissen,
okay, der Task, der dann auch läuft, der wird
später mal irgendwas Böses machen oder
vielleicht noch irgendwie, keine Ahnung. Und da muss ich auf jeden Fall
dran denken, dass der mir vielleicht irgendwie dazwischen
grätscht oder ich muss hier mal einen Lock setzen, damit das irgendwie
atomar bleibt und keine Ahnung.
Das heißt,
ich kann nicht mehr sagen, okay,
ich habe jetzt diese Funktion aufgerufen,
ist es gut, ich weiß jetzt Bescheid,
es hat funktioniert oder nicht
und ich mache jetzt weiter, sondern
ja, ich habe dieses Future-Ding in der Hand,
aber tatsächlich muss ich
mir irgendwie selber merken, was da noch alles
passieren kann und das ist natürlich schlecht,
weil das macht halt genau diese lokale,
dieses lokale Nachdenken
über Code kaputt und er sagt
halt so, alle Concurrency-Lösungen, die
dazu führen, dass man nicht mehr lokal
über Code nachdenken kann, das ist
alles, das ist alles nicht richtig,
Das sollte man so nicht machen.
Was ist da die Lösung jetzt davon?
Er hat da so ein Konzept,
das heißt dann irgendwie
Nurseries.
Nurseries, die kleine Krankenschwester,
die die Babys auf der Aufzuchtstation ist.
Genau, er sagt so, ja, so Tars
oder sind so wie so kleine Kinder,
die darf man nicht einfach so frei rumlaufen lassen,
das ist nicht gut.
Die muss man irgendwo einsperren,
wo sie dann gepflegt werden.
Wo sich jemand drum kümmert.
die dürften aber nicht raus. Ja, genau.
Und das Ganze ist in so einem Context-Manager drin
und tatsächlich, also ich habe noch nicht
so viel damit rumgespielt. Also es sah gut aus, aber
ja, angeblich
ist das wohl eine Möglichkeit,
das so hinzukriegen, dass
dass man weiterhin lokal über Sachen nachdenken kann
und dieses Problem, dass man
Spalter-Effekte hat, gar nicht mehr bekommt.
Und es ist sogar teilweise
einfacher, Sachen damit umzusetzen.
Es gibt da diesen für IP
Happy Eyeballs-Algorithmus,
der auch in Twisted drin ist. Und es gibt eine Twisted-Implementierung,
die ist 120 Zeilen
und relativ fies. Und es gibt eine
in Trio und die ist halt irgendwie,
weiß ich nicht, also ich meine, obwohl Zeilen
vergleichen ist auch wieder ein bisschen Quatsch, aber
also viel, viel weniger und viel
klarer. Und als er das Ding
in Trio nachgeschrieben, hat er auch diverse logische Fehler
in der Twisted Implementation
gefunden, weil das einfach
super schwierig ist, das so hinzukriegen
mit den Futures. Also in
Trio gibt es keine Futures mehr,
es ist halt eher so, es gibt diese Nurseries
und ja, es wurde auch schon
darüber nachgedacht, ob das nicht vielleicht eine gute Geschichte
wäre, das in
Python direkt einzubauen
und statt AsyncIO zum Beispiel
zu verwenden, aber das ist alles
noch gerade so dabei,
quasi noch nicht sprunghaft.
Ist der Zug nicht schon längst abgefahren?
Vielleicht schon, ja.
Ja, vielleicht ist er das schon.
Viel zu viele Leute, oder zu viele Leute
verwenden Async.io, als dass man
das noch vielleicht ändern könnte. Und es gibt halt da
diesen Ökosystem-Split und
wahrscheinlich ist es besser, dann eben
auf das zu versetzen, was eh dabei ist.
Trio macht das sowas, du hast jetzt gesagt,
Kontextmanager, das heißt, man muss diesen lokalen Scope
nicht verlassen. Ist das nicht eigentlich das, was Funktionen
tun, sowieso schon?
Ja, ja, aber Funktionen funktioniert halt nicht so richtig.
Weil?
Die Tats laufen ja weiter.
Das ist halt auch bei
wenn du halt eine Funktion
wenn du
Concurrence irgendwas machst, dann
hört das halt nicht in dem Moment auf, wo du das
aufgerufen hast, sondern das läuft halt unter Umständen weiter.
Das heißt, ich habe beispielsweise nur
den halben Whisky eingeschenkt und die andere
Hälfte, die kommt aber noch.
Aber woanders fängt der halt an, dann schon
andere Limetten rein zu
Ja, also
Und was ist der Unterschied?
in Trio, dann macht er dann trotzdem erst den einen Schritt fertig?
Oder wieso ist das so isoliert?
Also, dass du vielleicht bei diesem Barkeeper-Beispiel
das so anschaulich hinzubekommen
kriegst? Weiß nicht, ob ich das tatsächlich hinkriege.
Also, kann man sich, müsste man
sich selber angucken. Da gibt es auch Schaubilder auf der Seite.
Aber das zu erklären,
weiß ich nicht, ob das... Das ist so ein bisschen das Problem,
das generelle Problem an Current Programming,
oder? Dass diese Sachen alle gleich so kompliziert
werden, dass man dann diverse Schaubilder
braucht und Leute dann
irgendwann sagen, ja, lass lieber die Finger davon,
das ist nicht so. Ja, und tatsächlich ist das
vielleicht gar keine so schlechte, ich glaube, ich würde auch sagen, also auch meine
Erfahrungen, die ich damit so bisher gesammelt habe,
die waren alle immer, es war immer
ziemlich fies, also das war immer,
also die Beispiele,
die haben immer funktioniert, wenn man sich irgendwie
so Tutorials oder so anguckt, wenn man es
dann tatsächlich ausprobiert mit irgendwie
in den Fällen, wo man es dann halt
wirklich braucht, wo man dann viel Last macht,
dann sind mir jedes Mal
passieren komische Sachen
und das Debugging ist jedes Mal
Das ist so bei Ginkgo Program, da passieren immer
komische Sachen. Ja, also wirklich, also
zum Beispiel einen Bug
und diese
Geschichten, ich meine, das passiert anderen Leuten auch.
Zum Beispiel
der Gründer von
der ursprünglichen Entwickler von
Twisted hat einen langen Artikel darüber geschrieben,
warum er Multithreading hasst.
Wo er dann geschrieben hat, sie hatten
also Probleme und sie hatten dieses
sie hatten einen wirklich fiesen Bug
in einem größeren System und
der ist halt irgendwie nur
ab und zu aufgetreten. Sie haben es überhaupt niemals
reproduzieren können und sie sind es nicht losgeworden.
Und sie haben alles
from scratch nochmal neu geschrieben,
reimplementiert, um den Bug wegzukriegen,
weil sie ihn einfach über Monate nicht finden konnten.
Und das ist eigentlich schon echt bitter.
Es ist auch super schwer
zu testen, so Zeug. Das ist auch super schwer
zu sagen, wenn ich X mache und Y,
dann passiert Z. Sondern es ist halt,
wenn 37 Leute gleichzeitig X machen
und einer von denen aber Z macht und
einer von denen Y und
23 A und B, dann
passiert irgendwas.
Und Buchstabensuppe.
Aber dann passiert Buchstabensuppe und das ist ein Bug.
Ja, was ich
da mal hatte, war halt, genau,
ich hab halt so was Webcrawler-artiges
geschrieben und
mit ein paar tausend Seiten und
weiß ich nicht, so hundert
Seiten gleichzeitig abfragen pro Sekunde oder so,
alles gar kein Problem. Aber so, okay,
gehen wir auf eine halbe Million oder eine Million und machen
das mal so irgendwie ordentlich, so mit ein paar tausend
pro Sekunde. Und dann passieren
plötzlich seltsame Geschichten.
Irgendwie sterben plötzlich
Sachen oder was ich dann hatte, es wird
plötzlich irgendwie seltsam langsamer.
Man weiß nicht warum. Plötzlich
kriegt man ganz eigenartige
Tracebacks aus den Tiefen von Python.
Also was ich dann irgendwie
rausgefunden habe,
das war halt irgendwie die Resolver-Library
auf meinem Mac. Ich habe es auf dem Mac probiert.
Die hat halt irgendwie angefangen, plötzlich Probleme
zu machen. Und
zum Glück auf Linux ging es dann. Das ist auch
immer sowas. Ja, Mac gibt es dann
vielleicht für Smoketest gar nicht
so schlecht. Der macht dann irgendwie
ein bisschen früher irgendwie
fängt er an zu rauchen.
Bei Linux gehen dann viele Sachen, wo der Mac
dann schon raucht, aber
das war, und da habe ich auch lange dran rumgedebuggt
und nichts gefunden und das ist ganz schrecklich.
Ja, Load macht
Dinge kaputt, die
schwer zu finden sind und schwer zu sehen
sind.
Die dann auch nur so sporadisch auftauchen.
Da wird es dann auf einmal statistisch, wenn du
sagst, okay, mein Programm geht
in 99 Prozent
der Abläufe.
Das ist dann der echte Bug. Das ist dann wie, dass in der Schaltung
irgendwo ein Käfer reingeklettert ist,
weil die Schaltung so groß ist, dass da irgendein Käfer dazwischen
passt und du weißt aber nicht, woran er liegt.
Ja, wenn halt der DNS-Resolver nur 99 Prozent aller Anfragen
korrekt beantwortet und in einem Prozent der Anfragen
halt abstürzt oder irgendeinen Quatsch macht,
dann hast du halt so statistische
Dinge. Aber das ist natürlich sehr unbefriedigend,
weil ja eigentlich,
also als Softwareentwickler
oder als Informatiker ist man ja gewöhnt, dass wenn es
geht, dass es dann zu 100 Prozent geht und
immer.
Ein anderes Beispiel, eben
Lukas Langer, der hat ja bei Facebook
gearbeitet und hat dann auch so ein Beispiel für,
sie hatten halt irgendwie ein Ding, was halt auch
Async.io gemacht hat und dann
haben sie da auch Durchsatz,
wenn es anfing, so richtig Durchsatz zu machen,
wurde es plötzlich irgendwie magisch
langsamer.
Das sind die schlimmsten Sachen.
Sie haben dann irgendwie auf ihre Kurven geguckt
und sie haben es nicht verstanden und dann, bis dann
irgendwann jemandem aufgefallen ist, oh,
wo kommen eigentlich diese Kurven her?
Es gibt da halt noch einen Thread, der guckt sich halt an, was die anderen Threads so machen und was die anderen Tasks so machen. Und der hatte halt in der Art, wie er dann halt die Ergebnisse von dem, was er gesehen hat, wie er sammelt hat, irgendwie so einen naiven Algorithmus drin, der mit der Last nicht gut klargekommen ist.
der dann halt schnell langsamer
geworden ist und der wurde dann so langsam, dass er alles andere
aufgehalten hat und da ist dann
sozusagen die CPU rausgelegt
und ja, also
aber das sind alles so ganz ekelhafte
Probleme, also das ist
wenn man das nicht braucht, sollte man das nicht machen, glaube ich
das wäre so
Ja, oder halt sich möglichst
weiter von fernhalten, also ich meine, wir
sind ja Django-Entwickler und wir haben das ja schon lange
wir haben ja schon lange
Sachen, die konkurrent sind, weil wir halt
wenn du irgendwo was deployst, dann machst du halt
zehn Unicorn-Prozesse an oder so.
Aber die sind ja im Wesentlichen
unabhängig voneinander.
Die kommunizieren
nur über die Datenbank. Die Datenbank ist
da das, was die Currency macht.
Oder was die gleichzeitig
hat. Dass die Datenprobleme löst, dass das isoliert ist.
Genau. Da bin ich ganz froh, dass es
eine gute Datenbank gibt.
Genau. Wo ich einfach sagen kann, okay,
das kann ich messen, wie lange braucht
es, diese Query auszuführen
und wie viele können das gleichzeitig. Und wenn da zu viele
Leute gleichzeitig kommen, dann müssen die halt warten.
Wenn dann zu viele da sind, dann muss man halt die Timeouts hochstellen und sagen, fertig. Aber das ist so ein bisschen Concurrency Light, weil du eben die Sachen so sehr voneinander abtrennst, beziehungsweise das ist die smarte Concurrency. Du trennst die Sachen so weit voneinander ab, dass sie unabhängig voneinander sind.
Und wenn sie so unabhängig voneinander sind, dass sie sich gar nicht, dass sie keine Kommunikation machen müssen, dann kannst du sie auf verschiedenen Rechnern ausführen, dann kannst du sie skalieren, kannst du sie wegskalieren, ja, entweder über Prozesse oder über Prozessoren, über unterschiedliche Maschinen oder über, was weiß ich, Docker-Container, die dir dann, oder über einen Kubernetes-Cluster, ja, wo du dann halt im Prinzip das Gleiche an ganz vielen verschiedenen Stellen ausführst und das ist ein Modell.
Ja, aber nehmen wir jetzt mal den Fall, du willst jetzt eben sowas machen wie zum Beispiel, keine Ahnung, was mit Felix Elixier und Liveview geht, du hast halt eine Webseite und pushst den Leuten quasi reaktiv irgendwie Dinge in den DOM und du hast dann natürlich eine Websocket-Connection zu jedem Client und das können ja dann Tausende sein oder Zehntausende, dann musst du all diese Verbindungen irgendwie handeln, musst damit was machen.
wenn du jetzt dieses klassische Worker-Modell
mit Unicorn machst, das geht auch,
dann hast du aber irgendwie einen Haufen
Verbindungen und brauchst einen Haufen Server.
Wahrscheinlich kannst du es auch
mit einem machen. Ja, da würde ich
mir einfach wünschen, dass es sozusagen so eine
Verbindungsdatenbank
gibt,
die dieses schwierige Problem
wegabstrahiert, aber ich glaube, da gibt es noch nichts.
Ja, aber tatsächlich
mit Django 3.1
Async Views geht das tatsächlich.
Also ich meine, man kann auch einfach was anderes nehmen.
Also, womit man das schon länger machen kann, ist
wahrscheinlich sowas, wie man Starlet nimmt
oder so, oder irgendwas in der
Richtung. Ja, aber die nennen ja auch alle Async.io.
Also, die machen ja auch keine Magie. Genau,
genau, genau. Aber da ging das halt,
Django ging es bisher halt noch nicht, bis,
also jetzt geht es halt dann halbwegs. Was
macht Django denn jetzt alles so Schönes? Genau,
jetzt
kann es, also was neu
dazukommt, sind Async-Views,
wo man halt
sozusagen als View tatsächlich eine
Funktion hat, oder eben auch eine Klasse, wo man dann halt
die Call-Methode als async
def markiert,
also async-Funktionen hat, die
Views sind und
die dann
Co-Routinen zurückgeben und
dafür muss das Interface,
also das ist bei mir schon mit Django 3.0 passiert,
das Interface zum Server,
es muss möglich sein, was anderes zu benutzen als BSGI
und das, was man da verwendet,
ist halt dann ASGI
und das kann halt
beide Richtungen und
ja, ist halt...
Also Web-Server, Gateway-Interface und Asynchronos-Server.
Ja, genau.
Ist sozusagen das Übertragen auf den Fall,
den man jetzt halt dann hat.
Und genau, kommt auch aus dem Channels-Projekt irgendwie.
Andrew Godwin hat das Ding halt auch in den Standard irgendwie dafür
sozusagen hauptsächlich, glaube ich, irgendwie geschrieben.
Ist jetzt in der Version 2.0 oder sowas da
und ist auch mehr oder weniger fertig
und wird auch von allen anderen quasi so adaptiert.
Also das hat sich wohl tatsächlich mittlerweile eigentlich als Standard
für solche...
Hat sich durchgesetzt.
hat sich durchgesetzt für, das ist halt
der Standard, wie jetzt ein Applikationsserver mit der
Applikation irgendwie kommuniziert.
Und, genau.
Und
was in Django 3.1 jetzt dazugekommen ist,
sind die Views, das ging halt
in 3.0 noch nicht.
Middlewares,
und das war halt auch einer der
schwierigen Teile halt, das Problem ist, du musst
halt es hinkriegen, also wenn
eine synchrone Middleware dazwischen ist, dann geht es halt schon eigentlich
nicht mehr. Die ganzen
ein Middle-Wise-Async zu kriegen
und
auch Async-Tests gehen halt
auch. Und damit
ist halt tatsächlich schon mal was da, womit man
was machen kann. Ich meine, tatsächlich
also die Wunschvorstellung, die ich an das Ganze hätte,
eigentlich ist da so, dass
alle Dinge, die jetzt I.O. machen auf meinem Server,
also normale Webseite, kommt
ein Request rein, das Ding
macht halt irgendwie, keine Ahnung,
fünf Statements an den Datenbank,
fragt irgendwie
ein Redis-Cache, fragt
noch irgendeine API oder sowas
und gibt dann irgendwie eine Antwort zurück
in einem View und momentan ist es
halt so, da wartet man dann halt
synchron auf jede einzelne Anfrage, die man
irgendwo hinstellt und alle Latenzen addieren sich
und
bis man das erste Byte am Client
empfängt, muss man halt diese ganzen
Netzwerk
Zeiten
abgewartet haben und
das kann halt sein, dass das dann irgendwann, wenn man viele
Statements macht oder wenn man viele APIs fragt,
dann wird das halt viel und man kann
im Grunde nichts tun, so wirklich.
Oder man muss es halt komplett selber machen. Das Framework
gibt einem da nichts an die Hand, womit man das
irgendwie verbessern kann.
Und sozusagen in einer goldenen
Zukunft wäre es halt
vielleicht so, dass man sagt, okay,
das wird alles Async
zusammengesammelt. Alle Sachen, die
I.O. machen nach außen,
erwartet man halt.
Und
die Latenz, die man
als Client, wenn man die Seite
abfragt, zu sehen bekommt,
ist die, die der längste IO-Ding nach draußen braucht.
Aber alle anderen sind dann halt schon da.
Das heißt, es ist nicht mehr, alle Latenzen addieren sich,
sondern die Latenz, die man sieht,
ist die von dem längsten Einzelteil sozusagen.
Ja.
Aber ist das jetzt nicht Parallelität?
Nö, das ist Concurrency.
Das ist alles immer nur, genau.
Weil ich sehe da,
ich sehe echt einen ganz anderen Anwendungsfall
für diese Async-Views und Async-Middlewares und so weiter.
Ich sehe halt, dass du lange laufende Views hast
und nicht den Worker blockierst.
Das heißt, du kannst derweil andere Clients behandeln.
Ja, das gibt es natürlich auch.
Das ist ja genau das, was du bei WebSockets brauchst.
Du hast ja im Wesentlichen einen Request,
der für immer läuft.
Oder so lange, wie der Client halt da ist.
Und zwischendurch kannst du aber was anderes machen.
Und der kann prinzipiell ja dann auch mit anderen Views
kommunizieren. Du hast dich gerade
freiwillig gemeldet, nochmal zu erklären, was WebSockets sind
und weil das
kam heute noch gar nicht dran.
Ja, WebSockets sind, also
da muss man ein kleines bisschen
ausholen, glaube ich, weil
das, was man so als Webseite kennt,
das hat so ein Modell, das heißt Request Response.
Das heißt, du schickst eine Anfrage
hin und der Server
bearbeitet die und dann schickt er irgendwann eine Antwort
zurück und dann ist das abgeschlossen.
Das ist alles, was
da passiert. Also das, was man so hinschickt, ist dann so
eine Anfrage, entweder will man irgendwie aus dem
klassischen Crowdstream irgendwas machen, also
lesen oder schreiben oder
updaten oder löschen oder sowas und dann
bekommst du eine Antwort, die
dann irgendwie so einen Statuscode hat, den man vielleicht irgendwie so
kennt. Genau, das ist
alles Feinheiten, die da drin sind.
Dieser Request-Response-Zyklus ist einfach nur,
ich schicke dir eine Anfrage hin,
einen Arbeitsauftrag und der
Server bearbeitet diesen Arbeitsauftrag und
schickt dann das Ergebnis zurück. Und was da drin steht,
spielt erstmal keine Rolle. Das kann sein,
gib mir die Homepage, das kann auch sein,
update alle Bilder in der Datenbank
und es kann auch sein,
lösche alle, was weiß ich.
Das spielt erstmal keine Rolle,
sondern das Wichtige ist,
das ist eine abgeschlossene Welt.
Ich schicke eine Anfrage hin
und die wird bearbeitet
und dann wird sie zurückgeschickt.
Und wenn ich eine neue Anfrage hinschicke,
dann hat die mit der vorherigen erstmal gar nichts zu tun.
Man muss dann Tricks benutzen,
damit da sozusagen so eine Kohärenz da ist,
dass ich der eingeloggte Benutzer bin.
Aber im Endeffekt sind das alles Tricks,
um einzelne Request-Responses, um einzelne solche Zyklen so zu machen,
dass die ausschauen, als ob sie zusammengehören.
Du meinst sowas wie Session oder sowas?
Genau, das mit Cookies, wo du dann so eine Session-ID hast,
dann kannst du simulieren, dass diese verschiedenen Requests alle zusammengehören.
Aber im Endeffekt sind die alle unterschiedlich.
Die könnten alle an einen anderen Web-Server gehen
und es würde trotzdem funktionieren.
Und das ist in ganz vielen Fällen auch der Fall.
naja, wenn du bei Google die Hauptseite abrufst
und danach die Suche abschickst,
wirst du sicherlich nicht vom gleichen Rechner bedient werden.
Beziehungsweise du wirst eventuell sogar von ganz vielen Rechnern
gleichzeitig bedient werden,
weil die natürlich intern ganz viel Geschwindigkeit zahlen.
Aber das spielt gar keine Rolle.
Für dich als Client, als Browser,
ist die Welt eine ganz einfache.
Du schickst eine Anfrage und dann kriegst du eine Antwort zurück.
Und dann ist das abgeschlossen.
Und wenn du danach was Neues brauchst,
schickst du eine neue Anfrage, kriegst du eine neue Antwort zurück.
Bei WebSockets ist es anders. Bei WebSockets machst du eine Verbindung auf und diese Verbindung bleibt dann bestehen. Und du kannst dann über diese Verbindung Daten an den Server schicken. Der Server kann aber auch selbstständig Daten an dich schicken. Und das löst so ein Problem, was man früher hatte, wenn diese klassische, das klassische Beispiel ist eine Chat-Anwendung, wo halt einer was in sein Chat-Fenster eintippt und die anderen sollen das dann sehen.
Und bei einem Request-Response-Mechanismus heißt es, dass die halt die ganze Zeit fragen müssen, gibt es schon was Neues, gibt es schon was Neues, gibt es schon was Neues und der Server die ganze Zeit Nein sagt und irgendwann sagt er halt Ja, weil da irgendjemand anders was eingetippt hat.
Viel besser wäre es aber doch, wenn die alle sagen, ich bin jetzt hier und ich möchte gerne alle Nachrichten aus dem Chatraum hören und sobald es eine neue Nachricht in diesem Chatraum gibt, sagt der Server allen angeschlossenen Clients, hier ist was Neues.
Dafür braucht man aber so eine bestehende Verbindung. Das heißt, dafür kannst du nicht nur sagen, beantworte mal die Anfrage, gibt es was Neues, sondern da ist die Anfrage, informiere mich, sobald es was Neues gibt.
Man hat da früher ganz schlimme Technologien gemacht. Man hat dann irgendwelche Long-Polling-Requests gemacht oder irgendwelche Meteor-Sachen, die HTTP so ein bisschen verbogen haben, um das eben hinzukriegen.
Und hat dann irgendwann WebSocket zum Standard gemacht, was im Wesentlichen das macht. Das ist eine HTT, das ist erstmal eine normale HTTP-Anfrage, die dann upgradet wird, damit die Verbindung nicht geschlossen wird. Und diese Verbindung bleibt dann bestehen und ist dann bidirektional. Das heißt, der Client, der Browser kann Nachrichten schicken. Es muss nicht unbedingt ein Browser sein, kann auch was anderes sein. Und der Server kann aber auch Nachrichten schicken.
Und dadurch wird eben so dieses Modell, dieses Programmiermodell, was man früher hatte, ein Request kommt rein, erzeugt eine Response, ausgehebelt, weil ein Request kommt rein, heißt, wir verbinden, wir machen jetzt eine Verbindung auf und danach können sehr viele Responses darüber gehen.
Da können auch noch neue Requests drüber kommen, weil der Client halt, weil jemand was in sein Chatfenster eingetippt hat und der Client sagt dann, bitte veröffentliche das in diesem Kanal.
Das heißt, WebSockets sind so ein bisschen die Erweiterung,
ja nicht eine Erweiterung, sondern eine Möglichkeit,
rohere Netzwerkverbindungen zu haben,
länger bestehende Netzwerkverbindungen zu haben
aus normaler Browser-Hardware, aus normaler Browser-Software aus.
Es gibt inzwischen auch ganz viele andere Clients,
die WebSockets verwenden.
Die meisten Native-Anwendungen werden mit ihren Servern über Websockets kommunizieren, weil das eben der Standard ist.
Wie macht man sowas in Django?
In Django macht man sowas erstmal gar nicht.
Beziehungsweise jetzt in 3.1 kann man das eventuell machen.
Die Websocket-Verbindung muss vom Client aufgebaut werden.
Das heißt, der Client muss sich irgendwo anmelden und sagen, hier, ich möchte gerne einen Websocket haben.
und dafür gab es eben in Django
diese Erweiterung, die Channels heißt, weil
Django selber kann das nicht. Django selber hat nur den
Request-Response-Mechanismus.
Das ist
sofort ersichtlich, wenn man die erste View-Funktion schreibt,
weil die eben einen Request
kriegt. Und das ist genau der Request, der vom Browser
geschickt wird. Der sagt, mach mal
bitte Folgendes.
Und das, was eine View-Funktion erzeugt,
ist dann eine Response und das ist genau der
Abschluss dieses, sobald die View-Funktion fertig ist,
ist die Verbindung weg.
Um da
weiterzugehen, um da WebSockets machen zu können,
braucht man eben was anderes und das war früher Channels
und jetzt wandert das so langsam in Django
selbst rein. Wobei, also
das soll wohl nie tatsächlich nach Django reinkommen,
sondern Channels wird jetzt halt
das Ding zum Handeln von anderen
Protokollen, die nicht HTTP sind.
also, und zwar nicht nur
Das ist dann halt nicht, ja, das ist dann halt Django Channels,
sondern, also es ist quasi
Teil des
Django Channels macht halt sowas dann wie WebSockets,
aber halt nicht nur das, sondern halt auch WebRTC
und halt auch MQTT und so.
Ja, okay.
Also alles, was eben lange Verbindungen braucht.
Genau, genau. Aber du kannst es dann halt
schon auch an Django damit anbinden,
in gewisser Weise.
Genau. Und es wird halt natürlich in
Channels deutlich einfacher, weil wenn die Infrastruktur
für ASGI halt schon in
Django drin ist,
dann, genau, brauchst du da nicht nochmal einen
extra anderen Server oder so, dann kannst du einfach
deine ganz normale Django-Infrastruktur weiterverwenden.
Ja.
Ja, ja, genau, genau.
Okay, also das ist das halt, was ich da als Anwendungsfall sehe,
dass man da leichter sozusagen in diese Welt reinkommt.
Ja, also was ich total interessant finde,
also wie gesagt nochmal, also wenn ihr das nicht kennt,
Phoenix Elixier, würde ich mir ein Live-View angucken.
Ja, das ist super spannend.
Ja, was das Ding nämlich macht, ist, also man kennt das ja so,
also ich würde sagen, das, was halt jetzt die meisten Leute schon kennen,
Single-Page-App mit JavaScript, da funktioniert das halt so,
du machst halt irgendwie auch immer GraphQL oder REST
oder sonst was abfragen irgendwie
gegen ein Backend.
Und
da gibt es auch teilweise sowas wie WebSockets oder so,
aber im Grunde das ganze State Handling
deiner Applikation
machst du halt im Client.
Beliebig, eklig
oder halt auch gut, keine Ahnung.
Redux war eine Zeit lang in, ist jetzt nicht mehr so.
Jetzt gibt es halt andere.
Vuex.
Ja, und
aber im Grunde, du machst das halt
in der Applikation,
weil du dann halt auch
da das ganze
DOM-Diffing machen kannst und
dann halt nur die Sachen updaten, die wirklich geändert
werden müssen und
so. Und damit das alles funktioniert,
musst du das halt dann im Client machen und so.
Und
Phoenix macht das halt anders.
Das macht das alles auf dem Server.
Und das schickt sozusagen nicht
irgendwie
jetzt gedifft irgendwie den DOM zurück,
sondern es schickt dir halt sozusagen die Änderung
an deinem State
zurück an den
Client und da wird es halt direkt im DOM
geändert. Aber dadurch, dass das halt
sozusagen auf dem Server alles ausgerechnet wird, kann das sehr blöd
sein auf dem Client. Also da ist halt
irgendwie der JavaScript-Teil
von diesem
Live-View-Dings ist halt irgendwie so in so tausend Zeilen
und ich habe einen Vortrag irgendwie
von dem Entwickler davon gesehen, der meinte immer so,
also er muss immer aufpassen,
er hatte manchmal das Gefühl, er ist jetzt hauptsächlich JavaScript-Entwickler
und da muss er sich immer selber sagen,
nein,
Ich fand diese JavaScript-Frameworks
alle immer ganz furchtbar und
ich wollte das anders machen und
ich sollte nicht jetzt anfangen
irgendwie das nächste verrückte
JavaScript-Font endzuschreiben, sondern das muss
so wenig JavaScript bleiben wie möglich
und es ist halt auch relativ wenig, es sind halt irgendwie
tausend Zeilen oder so und
alles andere passiert auf dem Server
und das updatet
den DOM direkt.
Also was über die Leitung geht, ist tatsächlich nur
so etwas wie
Name des
Attributs von irgendeinem Formularfeld
oder sowas, dann neuer Wert und dann
wird es halt geändert und zwar direkt im DOM.
Und das ist halt natürlich nochmal
deutlich schneller, als man das normalerweise
so gewöhnt ist von den
JavaScript-Frameworks und
es ist halt weniger Kram auf der Leitung.
Was man normalerweise, was man selbst bei
diesen Single-Page-Apps-Geschichten halt
auf der Leitung hat, ist ja nicht nur
der Payload, der übertragen wird
von den APs
sozusagen, also weiß ich nicht, irgendwelches JSON,
wo halt auch ganz
viel immer dupliziert wird und
ganz viel Boilerplate dabei ist, sondern
was halt auch da immer noch mitkommt,
ist halt diese ganze Protokollgeschichte und
die Cookies, ja, so 4 Kilobyte-Cookie-Kram,
der da hin und her geschickt wird,
dann, und
es wird jedes Mal nochmal, auch
der Server muss immer nochmal, ach so,
ach, hier ist deine Signatur, ach, du bist der
User, ach, sehr gut, und, ja, alles klar,
ich merke mir das mal und vergesse es sofort wieder
beim nächsten Request, ja, das ist halt eigentlich,
wenn man sich anguckt, was da tatsächlich passiert auf der
Leitung, es ist alles ganz schön verrückt,
Und wenn man sich dem gegenüber anguckt,
was Elixir da macht, da geht einfach nur
die rohen Daten, die gebraucht werden,
um den DOM zu ändern, gehen über die Leitung
und sonst nix. Und das ist wirklich
super wenig.
Das klingt ziemlich schlau. Und der Witz ist,
genau das Gleiche könnte man mit Django
eigentlich auch machen.
Du brauchst eigentlich auch nur diese tausend Zeilen.
Ja, ich dachte auch schon,
ich dachte so,
vielleicht sollte man sich diese tausend Zeilen
JavaScript da mal genau angucken
und dann halt das Ganze mit Channels
oder weiß ich nicht, und WebSockets machen,
weil das man in den States
mit Async und so super handeln kann.
Das kann man in Python
und mit Django ganz genauso machen.
Da braucht man das Erlangen da gar nicht.
Ja, also genau.
Das ist halt so ein bisschen das Versprechen.
Und das wäre natürlich schon sehr cool,
wenn man sowas machen könnte.
Ja.
Genau.
Wir müssen noch ein paar Schlüsselwörter sagen.
bevor wir aufhören können.
Was ist denn ein Bier?
Soll ich mal einfach so Wörter haben?
Kooperatives Multitasking.
Ach ja, kooperatives Multitasking.
Genau, ja, wir haben jetzt noch gar nicht die wirklichen Unterschiede. Also, genau, es gibt jetzt unterschiedliche Ansätze, wie man diese Concurrency-Geschichte hinbekommt. Ah, soll ich ein bisschen was über Geschichte erzählen? Interessiert euch das?
Im 19. Jahrhundert, oder?
Also, damals. Also, wie Concurrency irgendwie nach Python gekommen ist. Ich weiß nicht, ich habe das, einen Großteil davon habe ich aus der…
Das hört sich an wie so ein Märchen, was man seinen Kindern erzählt. Wie Concurrency damals nach Python gekommen ist.
Ich kann nur diese Serie
von Lukas Langer
empfehlen, da habe ich jetzt einen Teil von dem,
was ich jetzt erzähle.
Und zwar ist es so Mitte der
90er oder so, gab es da halt so erste
Anwendungen für, man will
vielleicht diverse Dinge parallel machen.
Ach verdammt, jetzt bin ich selber in die Falle getroffen.
Concurrent machen.
Nebenläufig? Nebenläufig, ja.
Und zwar,
da gab es das Medusa-Framework
für und das wurde
zum Beispiel verwendet von Google.
dann, um den Webcrawler zu
bauen. Und so
ist halt Python ja auch irgendwie bei Google
reingekommen, halt über den Crawler.
Und das ist
auch irgendwann dann in die Standardbibliothek reingekommen
als AsyncCore. Ich glaube, das
Modul ist auch heute noch in der Standardbibliothek, aber
ja, deprecated.
Und
dann gab es halt
eine ganze Zeit lang
irgendwie so Ansätze, dann kam
irgendwie, glaube ich, zur Jahrtausendwende irgendwie so um den Dreh
irgendwie Twisted dazu.
wurde dann auch viel verwendet,
war aber immer inkompatibel
zum Rest von
Python. So die normalen Standard
Bibliothek-Funktionen, die blockieren
alle, die machen alle synchronen I.O. und so.
Das hat nie so richtig dazu gepasst. Das heißt,
es musste alles irgendwie anders gemacht werden. Das heißt, man konnte
Code, den man jetzt in Twisted,
wo man Twisted benutzt hatte, um das
Concurrent zu machen, nicht
jetzt mit irgendwas anderem verwenden, wenn man
jetzt vorhatte, auf G-Event umzusteigen oder so
ging das halt nicht.
Ja, und
aber das, aber Twisted ist auch ein riesen
Ding. Es gibt ganz viele Firmen, die das
für irgendwelche Netzwerkgeschichten benutzt haben.
In Apple hat das ganz...
Super viele Sachen, die man vorher einfach nicht machen konnte.
Genau, genau. Also war, ist schon ein
riesen Ding.
Der Mensch, der das entwickelt hat,
Levkovits,
glaube ich, der hat auch
den Pep zu Async.io mitgeschrieben.
Später, also
Async.io ist dann auch sehr stark beeinflusst
von Twisted.
Ein anderer starker Einfluss
ist Tornado.
Auch einer aus dem
Tornado-Projekt hat halt auch, ist einer
von den drei Leuten, die halt den
Async.io-Pep mitgeschrieben haben. Der andere ist
dann Guido.
Also Tornado und Twisted
haben das beide stark beeinflusst.
Tornado, auch eine ganz interessante Geschichte.
Ist auch ein Ding,
was Leute geschrieben
haben. Ich glaube, ursprünglich hat das mal
Brad Taylor geschrieben. Brad Taylor war bei Google
Der hat irgendwie Gmail gemacht
und Google Maps.
Und dann haben ein paar von den Leuten, auch Paul Buchheit
war, glaube ich, auch dabei, die haben dann
eine neue Firma gemacht, irgendwann so 2007 oder so,
Friendfeed. Ich weiß nicht, ob ihr euch
daran erinnert.
Ich habe es auch mal gehört. Ich weiß nicht, ob ich es mal benutzt habe.
Keine Ahnung. Ist dann von Facebook
gekauft worden.
2009.
Und
ja, Brad Taylor
ist dann CTO von Facebook geworden.
Und ich hätte ja
Das letzte zufällig war auch, glaube ich, in einer Podcast-Version mit Lukas Langer.
Der war ja lange bei Facebook und erzählte dann so,
dass intern bei Facebook ein großer Teil von Facebook ist halt irgendwie Python.
Fand ich überraschend, wusste ich gar nicht.
Und so komisch, wie kam denn da Python rein?
Ja gut, vielleicht über Instagram oder so, aber nee, tatsächlich irgendwie,
ja, der Autor von Tornado war halt CTO von Facebook lange Zeit.
Also ja, und hat da wahrscheinlich auch irgendwie seine Python-Vorlieben
vielleicht so ein bisschen ausgelebt.
Jedenfalls, genau.
Jeder bringt seine eigene Technologie mit.
Ja, genau.
Und ja, das Tornado ist auch heute noch irgendwie eine ganz interessante Geschichte.
Wird auch noch nach wie vor aktiv entwickelt.
Ist auch bei diesen Jupiter-Geschichten liegt das irgendwie drunter.
Ja, und genau.
Aber das waren halt alles Dinge, die unabhängig voneinander halt existiert haben.
Und mit Python 2 war das sowieso alles nicht so gut kombinierbar.
Und dann, genau, ist halt 2012, glaube ich, gab es dann so erste Ansätze dazu,
das mal dann tatsächlich in die Standardbibliothek und in die Sprache irgendwie reinzubringen.
Und ich glaube mit 3.4, das muss dann irgendwann so 2013 gewesen sein,
ich weiß es nicht so genau, ist dann halt auch sozusagen das in der Sprache gelandet,
beziehungsweise in der Standardbibliothek
mit diesen Dekoratoren für Async-Funktionen.
Und dann in 3.5 kam die echte Sprachunterstützung
mit Async-Dev und Await dazu.
Also ab dann gibt es eigentlich tatsächlich
richtig Unterstützung in der Syntax.
Ja, und es gab noch ein paar weitere Geschichten,
die dann auch später dazugekommen sind.
Da hat sich auch noch einiges getan.
Es ist heute viel angenehmer,
das Ganze zu benutzen,
also es ist viel angenehmer, das zu benutzen als früher.
Und es ist
eigentlich inzwischen richtig klasse.
Es ist aber
eine völlig andere
Geschichte als jetzt.
Es gibt jetzt auch andere Sachen, also man kann zum Beispiel
Multistriding
gab es in Python auch schon immer,
war in Python 2 ganz, ganz schrecklich,
weil
Noch schrecklicher?
Ja,
weil es tatsächlich so ein Lock-on-Tension
Problemen gab. Also einmal ist es natürlich langsamer,
als wenn es nur in einem Thread ist. Also je mehr Threads
man hat, desto langsamer wird es eigentlich.
Und Python 2 ganz besonders schrecklich auf mehreren
Prozessoren, weil da haben
die Threads sich dann tatsächlich um den Gil gekloppt.
Und ja, das Ganze wurde noch
viel schlimmer, langsamer. Aber auch
da seit Python 3.2 gibt es einen neuen
Jill. Also
in Python 2 wurde das so gemacht,
oder beziehungsweise vor Python 3.2,
dass
der Interpreter
alle 100 Ticks, also
Also ein Tick ist halt irgendwie so eine, ja, ich weiß nicht.
Das ist ein Opcode, oder, der ausgeführt wird.
Genau, das ist sozusagen eine primitive Operation,
aber das kann auch so was sein,
also wenn man sagt so for i in range eine Million,
dann ist das auch nur ein Tick.
Das ist so ein bisschen schlecht,
weil es kann halt sein, dass ein Tick sehr, sehr lange dauert.
Aber das Ding hat halt fix alle, nach 100 Ticks irgendwie geguckt,
okay, hat so eine Check-Funktion aufgerufen
und die hat dann einmal Signal-Handling gemacht.
Aber auch geguckt, okay, welcher Thread läuft denn gerade?
Muss ich da irgendwas, muss ich vielleicht einen anderen Thread
in die Warteschlange der Threads, die jetzt runnable sind,
fürs Betriebssystem reintun oder nicht?
Das ist auch so, dass Python-Threads
sind echte Betriebssystem-Threads.
Also was ich dann oft lese,
irgendwie ist sowas wie, ja, der Python-Interpreter
schedulet da irgendwas.
Nee, macht er nicht, das macht das Betriebssystem.
Aber der Python-Interpreter kann natürlich sagen,
okay, also dieser Thread hier wäre jetzt
theoretisch runnable. Wer dann
vom Betriebssystem
tatsächlich sozusagen, wo der Kontext-Switch
hingeht und welcher dann weiter ausgeführt wird,
das macht das Betriebssystem dann.
Ja, und... Und wie nennt man das,
Jochen? Jetzt muss ich kurz das Schlüsselwort dazwischen
sagen. Präemptives
Multitasking. Genau, und das ist...
Weil man zwischendurch abgebrochen werden kann. Präemptives
Multitasking, weil man selber
sozusagen, wenn man jetzt in einem Thread ist,
kann man nicht bestimmen, wann einem
die Kontrolle entzogen wird oder weil man...
Und es kann jederzeit passieren.
Auch in,
ich habe mich da mal mit jemandem
darüber gestritten und musste dann leider
mir zeigen lassen,
dass ich da Unrecht hatte. Das kann auch
innerhalb eines Python-Befehls sein.
Also Python-Befehle selbst sind dann
nicht atomar, sondern es sind eben diese
Bytecodes, die da drunter liegen, die atomar sind.
Aber so eine
Zuweisung wie i plus gleich
1 ist auch nicht atomar,
sondern das kann
zwischendurch unterbrochen werden.
Und das ist da die große
Gefahr daran, dass man eben innerhalb
eines Befehls, den man
selbst als
unteilbar sieht,
kann man irgendwie die Kontrolle
weggenommen kriegen, es passiert irgendwas anderes, jemand anders
ändert irgendeinen Wert
und man selber fängt wieder an
und plötzlich sind die Sachen anders, als man erwartet hätte
und es passieren schreckliche Dinge, ja.
Also das ist präemptives Multitasking.
Präemptives Multitasking, ja, genau.
Hat natürlich gewisse Vorteile,
aber es ist halt, also, ja, genau, aber erstmal, um das so zu, genau,
dass es präventiv ist und das, was man aber heute hauptsächlich macht
und was halt auch eine gewisse Geschichte, also auch schon immer eine Geschichte hatte,
auch, es sind halt diese sozusagen Dinge, die man innerhalb von dem Thread
oder innerhalb von dem Prozess ausführt, also wo das Betriebssystem gar nichts darüber weiß,
dass man das macht, wo man das halt selber sozusagen, ja, entscheidet,
dass man jetzt die Kontrolle abgibt oder
was anderes macht. Und das ist dann halt
kooperatives Multitasking. Und das ist halt
so das, was man kennt aus,
also in Java heißen die Dinger dann Green Threads
oder das ist halt auch das, was in Stackless
Python passiert ist oder das, was
G-Event gemacht hat.
Eventlets oder so. Ja, genau.
Eventlets,
LibEV liegt da glaube ich zum Beispiel
unter Umständen drunter
oder auch LibUV, also die
Eventloop
von Node.js.
Das ist, LibIW hat, glaube ich, Armin Rigo geschrieben, was ja auch faszinierend war, die gleichen Namen, die man, also manchmal, da tauchten viele Namen auf, die ich schon kannte.
Das sind erstaunlich wenige Leute.
Ja, erstaunlich wenige Leute. Ich kannte die aus anderen Teilen schon und dachte so, ach, die haben auch diese ganzen Geschichten da, da haben die auch alle irgendwie mitgemacht, das wusste ich gar nicht.
Also genau, Amin Rigo habe ich nur
gehört im Zusammenhang mit PyPI,
aber nie mit
PyPI,
aber nie mit
irgendwie so
Concurrency-Geschichten, aber ja,
der hat, glaube ich, eine Bibliothek
geschrieben, GreenLed,
die auf LibEV basiert
und darauf basiert wieder
G-Event und G-Event
macht halt quasi sozusagen
User-Space-Threads
und
macht da aber auch
teilt das irgendwie so halbwegs
zufällig ein, wann die laufen und wann die nicht
laufen und damit das
halt mit dem Rest von der
synchronen und blockierenden
I.O.
Funktion und so im Rest von Python
funktioniert, monkeypatchen sie einfach alles.
So zum Beispiel das Socket-Modul, ganz böse.
Das ist aber auch hart. Das ist ziemlich hart.
Okay, ja, das geht natürlich
auch so.
Das funktioniert.
Wir gehen jetzt erstmal überall rein und
Ja, also das ist schon bitter,
aber
zum Beispiel G-Event ist halt
das, was auch unter G-Unicorn liegt.
Deswegen heißt das Ding G-Unicorn.
Deshalb heißt es G-Unicorn.
Und genau.
Gab es nicht früher mal was, das hieß Green-Unicorn
und es ist dann so G-Unicorn geworden?
Ja, genau.
Und genau, das ist halt alles
sozusagen kooperatives
Multitasking im weitesten Sinne, wobei
weiß ich jetzt gar nicht, bei G-Event bin ich mir jetzt gar nicht so super sicher.
Ja, klar, bei G-Wand ist es auch kooperativ.
Ja, im Prinzip ist es auch kooperativ.
Aber jetzt, im Wesentlichen jetzt ist ja Ace & Geo oder so der...
Genau, das ist jetzt sozusagen der heißeste Scheiß,
sozusagen, den man jetzt da macht.
Und ehrlich gesagt, also ich habe ja jetzt da jetzt auch
eine ganze Zeit lang Sachen...
Das sieht auch deutlich besser aus als alles,
was man da so vorher gemacht hat.
Ja, aber im Wesentlichen heißt es doch,
jedes Mal, wenn du Yield sagst,
wird dir die Kontrolle erst mal weggenommen.
Yield?
Ja, nicht Yield, Await.
Ah, wenn du Await sagst, okay.
Ja, früher war es Yield.
Ja, yield from, genau, das war noch die
so tags davor.
Aber das ist so ein bisschen der zentrale Mechanismus,
oder? Dass du sagst, okay, ich mache jetzt
was und sobald ich await
sage, kann jemand anders was machen.
Genau, genau. Und das
hat eine interessante Auswirkung auf die
Art oder auf die Schwierigkeit, also wie schwer
das zu programmieren ist, weil wenn du präventives
Multitasking hast und an jeder Stelle kann im Grunde
die Kontrolle weggehen,
dann alle Dinge, die irgendwie
atomar sein müssen, musst du halt dann mit
Logs absichern.
Mit so kritischen Sektionen musst du sie absichern.
Und das Problem ist halt, du darfst halt nichts vergessen.
Und das kann halt überall passieren.
Ja, und selbst wenn du
nichts vergessen hast, kommst
du immer noch in so Deadlock-Situationen rein oder
in so Starving-Situationen.
Selbst wenn du alles richtig machst, kann es
immer noch... Wenn es eine Starving-Situation
ist, es wartet irgendjemand darauf, dass irgendwie
wer losrennen kann, aber da kommt einfach
nichts. Ne, das
ist ein Deadlock. Deadlock heißt
zwei oder mehr Dinge warten auf
sich gegenseitig. Und ein
Starving? Dann kann keiner loslaufen.
Und Starving heißt, jemand,
der etwas tun könnte, kommt nie dran.
Weil immer jemand anders
schon was tut. Das heißt,
dass der nicht selber gelockt ist,
sondern dass er einfach nicht
zu niedrig ist.
Oder weil er immer sagt,
macht ihr erstmal. Dass der sozusagen für immer
wartet, obwohl er etwas tun könnte.
Obwohl er nicht irgendwo...
Aber die können das ja alle schon so gut.
Ich bleib da mal hier stehen.
Genau, und sowas passiert dann halt.
Sowas passiert halt in so präemptiven Sachen,
weil du keine Kontrolle drüber hast, wer läuft.
Beziehungsweise die Kontrolle, die jemand hat,
ist eben das Betriebssystem.
Und das muss dafür sorgen,
dass so ein Deadlock entweder aufgelöst wird
und dass solche Starving-Situationen nicht passieren.
Ja, also es gibt halt diverse Techniken,
mit denen man die Probleme minimieren kann.
Es gibt dann so ein paar Patterns
Und wahrscheinlich würde ich auch sagen, also für die meisten Fälle nimmt man halt so einen Pattern und dann kann eigentlich nicht mehr so wahnsinnig viel passieren. Man nimmt halt eine Queue oder halt viele Queues und macht da halt Logs rein und da gibt es auch schon fertige Dinge, wo man die Logs nicht selber setzen muss.
Ja, aber auch da ist es erstaunlich leicht, in so Situationen reinzukommen, wo du dich deadlogst. Das ist erstaunlich leicht.
Ja, ja, ich würde auch sagen, also es ist halt
sehr scharfkantige Geschichte.
Ja, man muss da echt aufpassen
und genau, achso,
richtig, genau,
das habe ich eben nicht mehr erzählt, genau,
nach 100 Ticks immer diese Geschichten, aber das hat halt
diverse Nachteile, weil Tick kann halt sehr lange
sein und dann gab es halt auch diese
Battles über
wer kriegt den Gill
quasi auf unterschiedlichen Prozessoren und da so
war halt, das war, wie
David Beasley, gibt es halt
Understanding the Jill zum Beispiel,
den Vortrag von 2014
oder Verhalten auf
mehreren...
Also er sagte irgendwie auf
einer, also mit einem Stride, also alles gut, mit mehreren
Strides, nicht so toll,
auf mehreren Prozessoren, diabolical.
Das war wirklich irgendwie nicht schön.
Und
ja, das ist aber mit Python 3.2
besser geworden. Da gab es einen neuen
Jill und der macht das nicht mehr nach
Ticks, sondern es gibt jetzt einen Zeitintervall,
was halt eben
dazu führt, dass halt nicht
quasi Dinge für immer
warten müssen, weil halt
ein Tick halt super lang war.
Und zwar jetzt ist es halt so,
jetzt ist es nicht alle 100 Ticks, sondern jetzt ist es alle
5 Millisekunden. Man kann das aber auch einstellen, wie man
möchte. Also das konnte man vorher auch schon.
So alle 5 Millisekunden guckt halt der
Interpreter nach.
Muss mal jemand anders dran.
Bitte?
Muss mal jemand anders dran.
Ja genau, kann mal jemand anders dran oder
welches Schatz könnte laufen. Wobei letztlich, wer das
entscheidet, ist das Betriebssystem.
Ja, und das funktioniert jetzt deutlich
besser. Das funktioniert auf mehreren CPUs auch
gut. Ja, es ist nicht so, dass jetzt da auf mehreren CPUs
gleichzeitig was gemacht würde, aber es ist nicht
mehr so, dass die Performance viel schlechter ist, als wenn man
nur einen CPU hätte, was ja schon mal
auch nicht so schlecht ist. Genau.
Daher, also Threading kann
man auch verwenden. Also es ist auch nicht
so, also es funktioniert mittlerweile alles ganz gut auf
Linux. Also auch 10.000 Threads aufmachen,
gar kein Problem, funktioniert.
Ja, neulich hast du ausprobiert, Jochen.
Bei 9.500 war Schluss bei mir.
Aber
also das geht alles und das ist auch nicht
so, das findet man auch oft, ich war überrascht,
ich habe da so ein bisschen recherchiert, wie
oft da so Dinge auch in Büchern
drinstehen, ich habe zum Beispiel Fluent Python mir angeguckt
oder auch Effective Python von
Brad Slatkin, also eigentlich beides sehr renommierte
Quellen, weil ich dachte so, okay, so die
Standardwerke, da muss es doch drinstehen, wie es geht und die sagen
beide irgendwie, ah, Threads ganz schlecht,
du kannst irgendwie keine,
nicht so viele Threads aufmachen, weil
der Stackspace
im Betriebssystem riesig, brauchst
halt 8 MB, zum Beispiel sagt
Effective Python, bei Fluent Python
sind es halt auch immer Größenordnungen von, jeder Thread
braucht so Größenordnung MB, aber das ist halt nur
Virtual Memory, das ist gar nicht
Resident Memory, das heißt,
das stimmt so nicht.
Das ist viel weniger und das
Context-Switchen, also es gibt da auch so einen schönen Artikel, wo
jemand das alles mal gemessen hat und das ist,
eigentlich sollte das alles kein Problem sein.
Und vielleicht
war das früher auch ein Problem, weil auf 32-Bit
ist es tatsächlich blöd, weil der
REST-Space nicht so groß ist, aber 64-Bit
ja, sollte
alles kein Ding sein.
Und ja,
Context-Switchen ist auch so schnell, das sollte auch kein Problem sein.
Es könnte immer noch diese Log-Contention-Probleme
geben, aber ich weiß nicht so genau.
Naja,
und, achso, was auch so ist,
der Jail wird immer automatisch
abgegeben, wenn irgendwie so
Netzwerk-Blocking-Funktionen aufgerufen werden.
Dann ist der auch sofort immer weg.
Das heißt, das passiert,
selbst wenn man Präfix-Multitasking hat,
genau, passiert das automatisch.
Also muss man sich auch nicht selber drum kümmern,
sondern da gibt der Thread, der halt irgendeinen
blockierenden Netzwerkaufruf gemacht hat oder I.O.-Aufruf,
da ist der
Drill sofort weg.
Und ja,
also ich würde
sagen, mit Threads kann man eigentlich auch alle Sachen
so, also wenn es darum geht, I.O. zu
multiplexen, das kann man mit Threads auch wunderbar machen.
Es ist schwerer zu programmieren,
es ist halt ätzend, dass man nicht weiß,
wann die Kontrolle weggenommen wird
und so.
Es ist im Debugging schwierig.
Im Debugging ist es ziemlich übel, ja.
Probleme, die wir vorhin
erzählt haben. Da kommen dann halt irgendwelche Fehlermeldungen
von irgendwo her. Irgendein Callback
hat mal kurz gesagt, hallo, ich sterbe.
Dann steht man halt da.
Aber es geht auch. Und ich würde jetzt nicht
sagen, das kann man gar nicht machen, sondern
ja, es geht auch.
Aber tatsächlich,
Async.io würde ich auch sagen mittlerweile deutlich
besser, weil das ist jetzt
kooperativ. Da ist es so,
es dreht sozusagen die Geschichte um.
Bei Threads ist es so,
man kann überall die Kontrolle weggenommen
kriegen und Dinge sind bedroht, solange man
nicht gesagt hat, okay, ich locke das jetzt hier.
Ich benutze jetzt irgendeine Kerneldatenstruktur,
um zu sagen, da bitte nicht.
Dann ist das geschützt,
aber alles andere ist halt irgendwie
wilder Westen, Drachen
kommen vorbei, verbrennen an die Hütte.
Also ist halt, ja, weiß man nicht.
Und bei Async.io ist es quasi umgekehrt.
Da gibt es halt
die Stellen, an denen böse Dinge passieren können,
die sieht man, die sind markiert.
Da steht Await vor.
Und alle anderen Sachen, der ganze andere Code,
das ist einfach ganz normaler Code,
der so durchläuft, wo man sich sicher sein kann,
dass einem die Kontrolle da nicht weggenommen wird
und da kann man auch
Operationen machen und wenn da nur, wenn da
kein Await kommt, dann ist das alles atomar, weil
kann sonst ja gar nichts passieren.
Und das ist natürlich schön, weil
die Anzahl
möglicher Fehlerquellen wird halt deutlich
geringer, aber man
bezahlt natürlich in gewisser Weise einen Preis dafür
und der ist halt, naja, also man muss sich halt
auch selber drum kümmern, dass das halt,
dass man die Kontrolle abgibt,
wenn es geht, weil man alle anderen blockiert,
wenn man das nicht tut.
Man muss einfach kooperativ sein.
Man muss kooperativ sein.
Wenn man irgendwas macht, was nicht lange dauert,
dann gehen halt alle anderen kaputt,
was halt auch unter Umständen natürlich
sehr große Konsequenzen haben kann.
Aber da sieht man dann wenigstens.
Also ich meine, wenn du da dann den Interpreter unterbrichst,
siehst du, wo du bist.
Du siehst, wer schuld ist.
Genau. Es ist auch so, dass man kann,
ich glaube, Python-X,
wenn man Debug anschaltet
und Trace Malloc
anschaltet. Das sollte man immer machen, wenn man
irgendwie so Async-IO-Sachen zumindest
auf der Entwicklungsseite macht, dann
sollte man das immer anschalten.
Produktion natürlich unter Umständen nicht,
kostet auch Ressourcen, aber dann
sagt einem der Interpreter zum Beispiel so was wie
also hier hast du irgendwie
ein Task oder diese Funktionen, hockt
die CPU und zwar ganz übel, weil er das
intern halt aufruft mit einem
Timeout und das halt mitkriegt und dann
die Exception fängt, wenn
das halt zu lange dauert. Dann sagt er halt so, also
diese Funktion da, die macht irgendwas Böses.
Das sieht man dann tatsächlich in der Ausgabe
oder sagt einem auch, wenn man Sachen nicht
awaited hat und so. Type Annotation
ist auch total sinnvoll, vielleicht
bei so hakeligen Geschichten. Da kann
einem der Interpreter auch noch eine Menge sagen,
was da halt dann schief geht.
Weil er halt weiß, dass da jetzt eigentlich eine
Kurroutine zurückkommen sollte und so. Und wenn das halt
nicht passiert und dann, ja.
Also da geht
einiges.
Und es ist halt, wie gesagt, also die
bösen Stellen sind die, wo await davor steht und alles
andere ist halt sozusagen ein ganz normaler
Python-Code eigentlich.
Und das ist halt schon
schön. Und von den Ressourcengeschichten
würde ich jetzt zwar sagen,
nachdem ich mich so ein bisschen damit beschäftigt habe,
es ist nicht so,
ich weiß, es geht mit Swatch auch,
aber natürlich ist es auch so, dass
die sind schon ressourcenaufwendiger.
Also das habe ich
jetzt nicht nachvollzogen, aber Koroutine
ist halt eigentlich nur ein Funktionsaufruf und
braucht halt einen Kilobyte
Hauptspeicher oder so und davon halt ganz, ganz viel zu haben.
ist im Grunde überhaupt kein Problem. Du kannst
10 Hunderttausende davon haben,
kein Ding.
Du musst halt bloß schnell genug bleiben, dass du halt
tatsächlich, dass diese Hunderttausend Sachen auch irgendwann
alle mal wieder drankommen, aber ansonsten
geht das. Und
ja, da gibt es ja dann auch sehr schnelle Event-Gloops
drunter, also man kann halt auch, es gibt
die Referenz-Implementation der
Event-Gloob in Python,
die ist nicht schnell, aber die ist halt dafür da,
damit man weiß, wie es funktioniert.
Auch wenn man jetzt eine andere Implementation
schreibt, die auch dagegen testen kann, um zu gucken, verhält die sich
jetzt genauso, wie sie sollte und so.
Für Produktionen
kann man dann halt sowas nehmen wie
diese UV-Loop,
oder LeapUV, und das ist
die Node.js Event-Loop und die ist halt echt sackschnell.
Also, ja, und
damit kriegt man halt unter Python quasi da auch
dann die gleiche Geschwindigkeit hin.
Ja.
Haben wir erklärt, was eine Event-Loop ist?
Nein.
Ich hätte jetzt mal einen Vorschlag.
Ich würde jetzt auch so langsam mal die Kontrolle abgeben.
Ja, ja, ja.
und Sleep aufrufen.
Einmal Await machen.
Yield.
Ich würde einmal Yield sagen und dann direkt Sleep aufrufen.
Ja, ja, ja.
Das ist doch ein sehr schönes Stichwort, oder?
Ja.
Aber es hört sich für mich so an,
als ob wir noch mindestens zwei, drei Episoden
daraus machen müssen.
Vielleicht machen wir einfach noch eine.
Alle Worte gesagt haben, die gesagt werden müssen.
Also mir fallen noch viele Worte ein.
Ja, mir auch.
Dir fallen sicherlich auch noch ganz viele Worte ein.
Es ist auch, wenn ich mich so an diese Vorlesungen erinnere,
die wir da gemacht haben,
Und es hat eine gewisse intellektuelle Schönheit, wenn man diese ganzen Locking-Algorithmen dann hat. Wenn man die Dining-Philosophers einmal besiegt hat oder wenn man einmal die Lockless-Data-Structures alle erfunden hat. Das hat auch was Schönes, aber es ist nicht was, was man jeden Tag in seiner Arbeit machen möchte, glaube ich.
Nee, es ist wirklich schwer.
Das ist auch eine massive Fehlerquelle.
Ja, ja. Ich finde es auch
wirklich, es ist
hart. Also das ist schon so.
Mein Fuß brennt immer noch von so einem völligen
Vorfall.
Ja.
Ja, also es ist einfach
sehr leicht, damit Fehler zu machen. Und ich glaube,
dass das einer der großen Vorteile von
diesen ganzen AsyncIO-Sachen jetzt ist.
Wie du eben gesagt hast, der Code ist einfach
linear. Und nur wenn ich
Await sage, kann irgendwas Schlimmes passieren.
Ich bin in der Verantwortung, dass ich Await sagen muss,
damit ich kooperativ bin, damit die anderen auch mal
können. Aber solange
ich das nicht sage, passiert mir nichts.
Und das nimmt ganz, ganz, ganz
viele von diesen Ecken und Kanten
daraus, die einem sonst eben
ganz schlimm da reinfahren, die einem sonst die kritischen
Sektionen kaputt machen.
Und das
ist eine sehr gute Entwicklung. Ich begrüße
das sehr. Und das war ein sehr schönes Schlusswort,
lieber Johannes.
Alles klar, dann... Als ob ich es geplant hätte.
Ja, würde ich sagen, machen wir doch einfach
vielleicht dann. Ja, an dieser Stelle
bleibt uns gewogen. Hört uns, wann immer
ihr uns hört, lieber gerne immer weiter.
Abends, morgens, mittags, nachts.
An welchem Erdballteil ihr euch gerade
befindet. Oder
irgendwo out of space, man weiß es immer nicht genau.
Also.
Ja, schön, dass ihr wieder eingeschaltet
habt. Alle Kritik, Feedback und so weiter.
Hallo at peisenbockers.de. Bis zum
nächsten Mal. Tschüss. Bis dann. Tschüss.