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 beim 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 Multispelling 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.
Falls euch irgendwas gefällt oder nicht gefällt,
dann schreibt uns doch wie immer gerne eine E-Mail an
hallo.python.gc
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 wuhu!
Sehr cool, wir freuen uns.
Ich finde es toll.
Naja.
Dir reicht es noch nicht, du bist die Weltforscherin.
Du guckst zu viele YouTube-Channels.
Ich weiß nicht genau.
Ist das da so üblich?
Ich weiß nicht, ob das auf dem Podcast auch so üblich ist.
Ach was denn, ich habe mich einfach gefreut
Ja, ist schon toll, aber
keine Ahnung
Ja, wo wir gerade schon bei so anderen Sachen sind
Ihr habt ja vielleicht den Thomas gehört, der mit uns eine
schöne Folge gemacht hat und der hat
jetzt seinen Podcast umgenannt, 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 instead
Dads instead, und Kevin ist schon dabei
in einem letzten Talk und redet über PyMC3
Ich glaube, das ist sehr hörenswert
Ja, ich habe es gestern schon gehört, fand es sehr gut
Also, ja.
Ja, vielen Dank.
Und ich hätte 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
war auf jeden Fall eine
interessante Geschichte. Ja, hört doch da mal rein, wenn ihr möchtet.
Ja, wir machen
heute wieder Dango, vor allen Dingen halt, weil
Dango 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
Multispring? Wir hatten das in irgendeiner Episode schon mal so ein bisschen
angerissen, vielleicht auch so ein bisschen kurz
verbrochen, aber uns sind noch so ein paar andere Erkenntnisse
gekommen und darüber wollten wir
halt so sprechen. Warum
macht man so ein Spread 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 da noch
für Alternativen, wann braucht man das überhaupt
und warum und warum vielleicht auch überhaupt nicht
und irgendwie so.
Ja, wollten wir vielleicht erst mal
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 nur so ein paar Dinge aufgeschrieben.
Ich weiß nicht, ob du das verwendest.
Insofern kannst du vielleicht...
Pylance.
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 ziemlich coole Sachen 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 hab das auch schon
aktiviert und finde es auch ziemlich gut.
Also ich mache ja jetzt gar nicht so viel
mit Type-Annotationen, aber
die Verlockung wird stärker.
Und das Ding kann da
irgendwie einiges rausholen, ja.
Tja, Johannes, da bist du raus, denn du nutzt PyCharm, ne?
Ja, tut mir leid, ich hab die Features alle schon.
Ja, ich meine, ich benutze
ja auch PyCharm.
also insofern, also 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 wichtig.
Bei uns nutzen uns alle VS Code.
Achso, wer übrigens auch VS Code
natürlich nutzt, ist Daniel Feldtroy,
falls ihn kennt, der Autor von Two Scrooge 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 Twitch und er hat mir versprochen,
dass er in Düsseldorf zum Essen vorbeikommt.
Ich bin natürlich ganz gespannt, ob das irgendwie nicht nur blöd ist.
Ja, das kann man leicht versprechen, solange keine Flugzeuge fliegen.
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.
Das ist ja relativ gesehen nach Düsseldorf.
Kann man sich dann da Bücher signieren lassen?
Ja, also wenn die Altenbühne auf dem Ball, ja, das hat er ja auch gesagt.
Vielleicht verliege ich dann sogar dahin und dann quatschen wir ein bisschen.
Nein, das fand ich super, wollte ich nur mal kurz erwähnen haben.
Ja, aber es stimmt, ich gucke in letzter Zeit auch gerade in Vorbereitung auf diese Episode, habe ich relativ viele YouTube-Channels und so geguckt und da verwenden doch sehr viele VS Code.
Du hast dich vorbereitet?
Ja, ausnahmsweise mache ich das eigentlich nicht, aber ich fand es auch sehr unangenehm, ehrlich gesagt, wenn 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.
Ansonsten war ich 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, bald ist 3.9 durch.
Ja, bald kommt dann 3.9, genau.
Was ist denn das Tolle an 3.9?
Wie hast du das jetzt mal gefragt?
aus 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...
Was ist ein Subinterpreter?
Ja, das ist im Grunde auch so eine Methode,
um dann halt eventuell...
Also, ja, um halt in Gil so ein bisschen loszuwerden oder halt das so ein bisschen...
Gil ist der Global Interpreter-Log, ja?
Ja, um das so...
Da werden wir sicherlich gleich noch ganz viel drüber sprechen.
Genau, die Konsequenzen so ein bisschen zu mitigieren.
Und das sollte...
Obwohl, ich weiß es nicht, was ich da erzählen soll.
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-Analyse-Tools oder irgendwas benutzen.
Ja.
Aber...
Ja, diese Back-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.18
sind irgendwie vor kurzem raus.
Ja. Ja, also Django ist
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 dem persönlichen Setup.
Und zwar, genau, ich weiß nicht, ob man es hören kann, aber wir haben eine große Bohrmaschine genommen
und dann irgendwie immer die Außenmauer durchlöchert und jetzt ist hier tatsächlich kabelbasiertes Netz.
Oh!
Es könnte sein, dass es jetzt deutlich weniger knackst als vorher.
Also du meinst nicht, weil es weniger WiFi gibt und jetzt mehr konstantes LAN?
und es gibt halt richtig ordentliches...
Stimmt, ich sehe sogar da hinten das Kabel, das durch die Wand
in den Raum geht.
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
Caldigit Docking Station
besorgt. Eine was?
Caldigit.
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, weil ich jetzt Netzwerkkabel habe,
das Problem, okay, wie mache ich denn das
Netzwerkkabel an meinem Rechner fest, der hat ja nur OSWC,
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.
und das geht damit halt ganz gut, weil da steckt man einfach Ethernet hinten rein plus irgendwie das, was zum Monitor geht
und hat halt nur ein einziges Kabel, was zum Laptop geht und alles andere geht dann über die Dockingstation
und was tatsächlich funktioniert ist, ich habe da hinten halt dann noch Storage dran
und das ist schnell, also so eine externe SSD und das ist ordentlich schnell, der Monitor ist so ein ultrafein LG 5K
und da dachte ich auch so, oh, ob das funktioniert,
aber es funktioniert tatsächlich und es kommt auch noch Strom durch.
Also ich suche auch schon was ähnliches.
Ich möchte gerne meine Monitore umschalten
mit so einem Switch und zwar einmal auf
eine Workstation und einmal auf meinen
normalen Rechner.
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. Also falls ihr da irgendjemanden kennt oder
einen guten Tipp habt, her damit. Ich freue mich drüber.
und schaue ich mir an und probiere das mal aus.
Ansonsten, nö, sonst 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.
Vormaschine?
Ja, nicht in den Meters.
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.
Und das ist super.
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,
also vor einem anderen Schreibtisch in deinem Büro.
Naja, nee, ich habe ja zwei Arbeitsplätze in meinem Büro.
Ja, genau.
Und nicht auf einem anderen Arbeitsplatz.
Er ist ja Vatikan 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
Ja, cool, okay, dann würde ich sagen
von mir aus
tatsächlich das Thema
Ich bin absolut begeistert, das ist eine Weltpremiere
ja 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 mich da
Ich habe direkt mal eine Frage.
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.
Also erstmal nochmal
ganz kurz 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.
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 irgendwie 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 ja gleich sonst ein Exkurs
von mir zu EVE Online.
Ja, genau, das wäre interessant.
Aber die sind doch noch auf
2.7, die kriegen da ja doch die ganzen
Sachen gar nicht mit alle.
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.
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 Slackless Python.
Oh ja, das ist interessant.
Da umgehen sie ja gleich viele von den Dingen, was
halt mein Async überhaupt braucht.
Genau, also
beziehungsweise zu der Zeit, wo sie das
gemacht haben, gab es das halt einfach noch nicht.
Und Slackless 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
halt im Grunde braucht es keinen
Execution Stack dafür im Betriebssystem.
Kennst du die, was
Stackless Python kann, ist, du kannst diese Threads
picklen.
Ja, vor allem kannst du
mehr als einen ausführen, oder?
Ja, das auch, du kannst ganz gerne ausführen
Das hat auch keinen Global Interpreter-Log, das heißt, du kannst einfach
Also ihr erkennt jetzt gerade
wieder die ganze Bagage
mit dem Graphics-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, also
dadurch, dass diese Threads, also wenn ich jetzt zum Beispiel
halt ein Ding, ich habe keine Ahnung, wie die
funktioniert. Ja, ich kenne das nicht gar nicht.
Aber ich glaube, es geht irgendwie um Raumschiffe und so, die da
in den Weltraum rumfliegen.
Excellent Space.
Gut, wenn es Spaß macht, aber naja.
Und du hast jetzt irgendwie
einen Thread, der jetzt so ein Raumschiff simuliert,
das da so durch die Gegend fliegt, 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 riesen
Universum 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 die 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,
massiv nebenläufige Programme.
Also man braucht halt viel Concurrency.
und die Programmiersprache Python.
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
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
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,
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 sozusagen, also 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
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 Webentwicklungsgeschichten benutzt wird, Elixir.
Und da gibt es auch so ein Webframework Phoenix zum Beispiel
und da kann man auch mal sich angucken, so Phoenix Elixier,
LiveView,
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 man nicht so unterstützt wird
in den Frameworks und so, aber prinzipiell
geht das schon. Was macht das denn jetzt so
bei dir so schön?
Ja,
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, also vor 10 Jahren war es halt noch so
dass Computer 2 Cores hatten oder 4 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 10 Jahren noch kein Problem war
Moment, aber das ist jetzt glaube ich ein anderes Problem, oder?
Also aus meiner Perspektive ist es ein anderes Problem
Generell die
Nebenläufigkeit, die man da jetzt braucht
Aber das braucht man
Das haben die anderen auch nicht
Das kriegst du auch auf Node.js nicht hin
Das mag sein, dass
das mit Node.js nicht unbedingt hinkriegst
Aber mit C und Erlang und Rust
und so weiter kriegst du die Sachen schon hin
Und Go auch
Die nutzen schon alle Cores aus
Ja, aber da weiß ich gar nicht, ob man das unbedingt braucht.
Also da würde ich jetzt denken, warum?
Doch, also ich glaube, für mich ist das schon eine Motivation, mehr Core ausnutzen zu können.
Geht zwar nicht mit Async, das weiß ich, aber 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 Passing 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 Geschwindigkeit meint
ja wenn es um
quasi, wie schnell kann man Dinge machen,
geht, dann bringt einem das nichts, sondern
macht die Sachen langsam.
Nicht 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 danebenlä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 du da
bedenken musst.
Also multiprocessing parallel?
Dann hast du ja schon Parallelität. Mit NumPy kriegst
du die Cores schon alle voll.
Ja, klar, genau. Insofern würde ich sagen, das ist auch ein Problem.
Vielleicht müssen wir erst noch erklären, was Parallelität und Nebenläufigkeit sind.
Ja, bitte, bitte. Einmal kurz da einschalten.
Ja, aber ist
Multiprocessing nicht sowas wie
parallel?
oder...
Ja, Multiprocessing 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 musstest,
umso schneller war das dann halt.
Das heißt, im Wesentlichen warst du da gar nicht
durch 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.
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 du kannst sagen, hier irgendwie...
Ja, umso besser.
Aber dann hast du trotzdem noch
irgendwelche Locking-Mechanismen, die dir da
gut erraten mussten.
Aber wenn du CPU-bound bist, ist das alles nicht mehr schlimm.
Also das ist alles...
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...
Python ist 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.
Achso, ja, okay.
Aber das ist, also
ich habe hier gerade die...
Das ist jedenfalls 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.
Auf allen
Teilen dieser Tabelle möchte ich
jetzt ausgerechnet haben, was die Summe ist.
Genau.
Also ich habe hier die
Definition von
Rob Pike,
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 hätte ich erst mal.
Ich dachte, das hätte ich gerade.
Nee, das fand ich jetzt auch
nicht arg erhellend, aber
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
ein paar durchprobieren
ist das 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 hei du machst mehrere Sachen gleichzeitig Und Nebenl oder Concurrency hei du machst mehrere Sachen nebeneinander her
Also nicht an einem abschließenden Schritt erstmal den einen Drink mixen,
sondern fünf Gläser hinstellen, jedes Mal einmal ein bisschen Zitrone rein und dann ein bisschen Drink.
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 1, dann machst du was an Drink 2, dann machst du was an Drink 3.
am Ende sind alle fertig. Die Gesamtzeit
ist dann ja genau dieselbe, also
du wirst ja fünf Einzel 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, du kannst halt den Nächsten bearbeiten, während einer noch,
weiß ich nicht, während in einem irgendeine
fürchterliche chemische Reaktion läuft, die halt eine Zeit lang
braucht und du wartest halt jetzt nicht stumpf
davor ab, sondern du wartest auf den
Assistenten.
Der Erste, der sonst seinen Drink sofort bekommen hätte, weil er das erste
in der Stange stand, der muss jetzt länger warten.
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.
sein, 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
arbeiten, also nicht nur den Barkeeper, sondern
auch 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.
Ja, genau. Wenn du Abhängigkeiten
hast oder wenn du Wartezeiten hast, die kannst du
überbrücken, indem du was anderes machst. Und das ist
Concurrency. Du machst nie Sachen gleichzeitig.
Der Bartender kann nie
mehrere Sachen gleichzeitig machen.
Die magst du keine 5 oder 6 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
5 mal 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,
mehrere Sachen identisch
gleich machen können, dann könntest du
5 identische Drinks gleichzeitig
zubereiten.
Da wirst du jetzt keine
Analogie in der echten Welt.
Aber Async
ist jetzt Parallelität oder
Concurrency? Also ich würde sagen,
dieses Problem Parallelität
ist, also dass du beides gleichzeitig brauchst,
also 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 habe mir viele Sachen vorgestellt
Autonomes Fahren
oder Sport
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 konkurrent
Du machst das Auto fahren gleichzeitig
Nein, das fahren alle gleichzeitig
und alle müssen gleichzeitig darauf reagieren
und du möchtest ja für alle gleichzeitig irgendwie Werte haben
und möchtest dann das ganze Team
Das verstehe ich nicht, tut mir leid
Also du hast mehrere Fahrzeuge
Du hast mehrere Fahrzeuge
Du hast so einen Rechner, auf dem 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
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 Ergebnismöglichkeiten irgendwie so.
Der Dominik überspringt so die simplen
Schritte.
Also, der macht direkt komplett.
Ne, tu mir leid.
Das ist kein Newscase.
Vielleicht doch.
Der 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 musste 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?
Nein, nur ganz viel drüber gelesen.
Ich habe es tatsächlich auch mal ausprobiert.
Ich muss gestehen, ich war nicht in dem Boot.
Das habe ich auch nicht geschafft.
Aber es gab tatsächlich tolle Schlachten.
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 WTLM-Kapital vernichtet gleichzeitig,
weil man irgendwelche Sprungtore 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 aber in diesem Spiel
echt Gelddinger 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,
sich gegen das in die Luft sprengen und das halt alles auf dieser
spielerischen Karte, ohne dass das reale Auswirkungen hätte,
außer wirtschaftliche, für die Jungs,
die da vor dem Rechner saßen,
dann war das schon irgendwie sehr faszinierende
Geschichte, die da irgendwie losging.
Aber guck mal, Jochen, das ist doch ein perfektes Beispiel.
Du hast ganz viele Spiele, 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 Spiele-Experte, insofern
keine Ahnung, aber ich würde jetzt mal
und sagen, Spiele, die sind alle nur
concurrent. Da brauchst du nix.
Wenn ich jetzt so gegenseitig spiele,
ein ganz klassisches Killerspiel, ja, und wir schießen beide
gleichzeitig aufeinander.
Wo brauchen die Spiele denn bitte CPU?
Die brauchen eine offene 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 Timestep
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
arbeiten 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 gelogen. Das waren 250.000
Instanzen mit jeweils
maximal 50 Leuten, weil da einfach
die Auslastung
ist der Prozessor voll.
Und da ist
Parallelität einfach
da.
Je mehr Parallelität du nutzen kannst, umso höher
kannst du diese Zahl setzen.
Umso weniger Instanzen brauchst du.
Da ist Geld drin und da ist richtig...
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.
Die Frage ist halt, wo ist der Flaschenhals?
Der Flaschenhals heißt, das ist CPU, das ist dann sowas wie Netzwerk.
Ich glaube eher Concurrency und Netzwerk.
Da müsste man Peer-to-Peer vielleicht machen, das würde vielleicht schneller gehen,
über Peace verteilt, als dass man irgendwie alles durch einen Hals schickt.
Bei allen Leuten irgendwie so ein bisschen...
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.
Okay.
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.
und Jochen unterhalten sich über die Programmiersprache Python
Na klar. Also außer du kodierstststststststststststststststststststststststststststststststst
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 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.
Ja gut, aber dann hast du halt 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 Python. 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 Web-Server
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 Testprobleme hast,
plus irgendwie CPU, dann kannst du es vergessen.
Dann 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 da keine Panik verursacht. Kann das sein?
Ja, das habe ich jetzt genau.
Aber das waren Threads tatsächlich, keine Prozesse.
Also mit Prozessen würde 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.
auf Catalina macht das halt sofort
Kernelpanic, wenn man 10.000 Threads aufmacht.
Also die Lüfter gingen 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,
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
also ich meine, dieses
berühmte C10K Problem
wie schaffst du es, einen Web-Server
zu machen, der 10.000 Clients
gleichzeitig benutzen, bedienen kann
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.
Aber ich finde bestimmt irgendeine Workload, wo du noch was berechnen musst.
Ich glaube auch, dass es sowas tatsächlich gibt.
Aber es ist so einfach, dass man sagt, ich kenne das ja dann immer so, dass Leute sagen, das ist ja gar keine richtige Programmiersprache.
Aber ich meine, wer hat solche Probleme?
Ich hatte sowas ehrlich gesagt noch nie.
Und ich habe schon eine Menge Zwochs gesehen.
also
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
wir haben auch schon viele Sachen gesehen, aber wir sind halt
in Python unterwegs, 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
dieses 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,
besser benutzbar war
und ja.
Ja, auch ein besseres Programmiermodell hat,
oder? Also dieses
Promisers
und Futures und so weiter, das
ist schon sehr einfach.
Ja, aber das ist eigentlich alles, sozusagen
das gibt es halt in Python ja auch
Ja
Was gibt es denn da?
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, es ist sehr vergleichbar zu
zu Python, hat die gleichen Beschränkungen.
Da gibt es auch in GIL
ganz genauso wie in Ruby on Rails
und sonst irgendwie in PHP.
Die ganzen Skriptsprachen 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
und dann kann man halt sozusagen Callbacks auf dieser Event-Loop,
oder sagen wir mal so, das ist halt das, was ganz früher schon immer,
ich glaube, das ist schon immer möglich, 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 lineare Programmierung mehr.
Hast du was gesagt? Hatte ich irgendwas gesagt?
Vielleicht gab es 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 doch jemand anders. Ach Moment,
da war doch jemand, der hat aber was gesagt.
Ach Callback, achso da hinten, ach nee, da unten.
A, O. Das ist ja gar nicht so schlimm.
Diese Vermischung 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 kannst dein Programm 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 and 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 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.
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.
Das ist auch in dem Async-Teil,
man muss das wahrscheinlich
alles ein bisschen voneinander unterscheiden.
Es gibt 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ösungen für diese Conferency-Geschichte
ist halt... Ja, sogar in der Sprache,
oder? Ist nicht in der Bibliothek, sondern ist
richtig in die Sprache integriert mit den
Schlüsselwörtern. Ja, aber das ist
auch eine gute Sache, dass es
voneinander getrennt. Also was in der Sprache
tatsächlich drin ist, sind
halt Async-Funktionen.
Also wie man halt mit Async-Def
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
Kurroutine 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 halt
Async-Def und Await auch in Trio verwenden
und Trio verwendet ein ganz anderes Modell unten drunter als
jetzt Async-Trio.
Das ist eine
Implementierung,
sowas ähnliches wie AsyncIO, bloß
mit einer etwas
moderneren, etwas anderen Zielsetzung. Also es gibt
diverse. Es gibt AsyncIO,
ist in der Standardbibliothek. 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 advancer
Version von Nathaniel Smith
im Trio.
Und das Ding macht
im Grunde sowas ähnliches, aber halt
und anders. Also die Art, wie man es programmiert, ist halt anders.
Und benutzt aber Async-Dev 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 Core-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 Kohlberg-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
ein großer Teil der Probleme, die wir hier
sehen, sind die gleichen Probleme,
die Leute früher mit Gotoh hatten.
Oder er sagt,
das ist halt eine sehr gute Analogie dafür.
Wir sind in der Assembler-Welt angekommen, wenn wir über Gotoh
sprechen? Ja, äh, nee, nicht ganz
Assembler. Ganz viele Sprachen, die Gotoh haben.
Ja.
Also, äh, ja, also, ähm,
das Problem bei Gotoh ist halt irgendwie,
dass es dir, das ist nicht,
das ist, 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, äh,
er macht halt immer, er geht von einem Gotoh zu einer
Zeile und dann, er macht das halt immer weiter,
bis du halt siehst, das ist ein riesiges Spaghetti, ein riesiges Spaghetti-Kneuel.
Das heißt, du weißt halt
nie genau, ähm,
wie du eigentlich hingekommen bist
und wo es hingeht
und zum Beispiel kannst du halt keine Facebacks
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, die
irgendwie, 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. Also 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 man
irgendwie, 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
und Jochen unterhalten sich über die Programmiersprache Python
Ende der 60er, Anfang der 70er
Dijkstra und so, da gab es halt den berühmten Artikel,
die haben sich da Gedanken gemacht
und deren Vorschlag war halt,
ja, Guto 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 Guto eigentlich ganz gut,
auch sehr interessant.
Knut?
Ja.
Don't Include.
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 3%
rausholen kann, dann ist es nicht mehr premature.
Jaja, das war...
Ach ja, andere Zeiten.
Ja, jedenfalls.
Genau, der war da auch nicht unbedingt
so totaler Fan von Gotoh rausschmeißen, weil
und eine Frage im Moment 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 so.
Ja, und vielleicht wird es
dann sogar langsamer, weil eben diese
Funktionsaufrufe und diese ganzen Strukturmechanismen,
die brauchen ja auch Rechenzeit.
Ja, natürlich. Und Speicherplatz.
und wenn du nochmal 3% irgendwo rausholen kannst,
dann kannst du das auch machen.
Und wenn der Mainframe super teuer ist
und Arbeitskraft super beliebt,
dann macht es vielleicht sogar Sinn.
Aber heute...
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,
bei Concurrent
Programmierung hat man im Grunde in gewisser Weise das gleiche Modell und
er sagt zum Beispiel, Futures findet ja 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, es 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 ausgesehen weiterläuft,
drauf ausgeguckt hat.
Das heißt, du musst wissen, okay,
der Task, der da noch 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 gratscht
oder ich muss hier mal ein 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, es ist 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 es macht halt genau
diese 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
nicht richtig. Das sollte man so
nicht machen. Ja, was ist da die Lösung
jetzt davon? Ja, also er hat da
so ein Konzept,
das heißt da irgendwie
Nurseries.
Nurseries, die kleine Krankenschwester,
die die Babys auf der Aufsatzstation 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ürfen 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,
auf Ja angeblich ist das wohl eine M das so hinzukriegen dass man weiterhin lokal Sachen nachdenken kann und dieses Problem dass man Spalter hat gar nicht mehr bekommt
Und es ist sogar teilweise einfacher, Sachen damit umzusetzen. Es gibt ja 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 Zeilenvergleich ist auch wieder ein bisschen
Quatsch, aber also viel, viel
weniger und viel klarer.
Und als er das Ding in Trio nachgeschrieben hat, 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
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
Der Zug ist nicht schon längst abgefahren, weil
der ist ja jetzt schon drin in Python
Ja, vielleicht ist er das schon,
viele Leute verwenden
AsyncIO, als dass man das noch
vielleicht ändern könnte und es gibt halt da
diesen Ökosystem-Split und
und ja, wahrscheinlich ist es besser dann eben
auf das zu versetzen, was eh dabei ist.
Also Trio macht ja 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 Asso, 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. Ja, genau. Aber woanders fängt der halt an,
dann schon andere Limetten reinzubekommen.
Und was ist der Unterschied in Trio? Da macht er dann trotzdem erst
den einen Schritt fertig? Oder wieso ist das so isoliert? Also vielleicht
bei diesem Barkeeper-Beispiel das so anschaulich hinzubekommen? Ich weiß nicht, ob ich das
tatsächlich hinkriege. Also muss 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 Concurrent 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 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 Google, da passieren immer komische Sachen.
Ja, also wirklich, also
zum Beispiel einen Bug,
da habe ich jetzt noch, und diese
Geschichten, ich meine, das passiert anderen Leuten auch.
Zum Beispiel der
Gründer von,
der ursprüngliche Entwickler von Twisted
hat einen langen Artikel darüber geschrieben, warum man Multithreading
hasst, wo er dann
geschrieben hat, sie hatten also Probleme
und sie hatten dieses
sie hatten einen wirklich fiesen Bug in ihrem
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
und 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
Buchstabensuppe
dann passiert Buchstabensuppe und das ist ein Bug
ja, was ich da mal hatte
war halt, genau, ich hab halt
so ein Webcrawler-artiges geschrieben
und
mit ein paar tausend Seiten und weiß ich nicht, so
100 Seiten
gleichzeitig abfragen pro Sekunde oder so, alles gar kein Problem.
Also 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 an zu rauchen
dann heißt das schon, so bei Linux
gehen dann viele Sachen, wo der Mac dann schon raucht
aber also 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.
Und
die dann auch nur so sporadisch auftauchen.
Da wird es dann auf einmal statistisch, wenn du sagst, okay,
mein Programm geht in 99%
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,
Wenn halt der DNS-Resolver nur 99%
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%
geht und immer.
Und nicht eben...
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
und sie haben dann
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.
Ja, also, aber das sind
alles so ganz ekelhafte Probleme.
Wenn man das nicht braucht, sollte man
das nicht machen, glaube ich.
Ja, oder halt
sich möglichst weit davon fernhalten.
Also ich meine, wir sind ja Django-Entwickler
und wir haben das ja schon lange.
Wir haben ja schon lange Sachen, die
Concurrency sind, weil wir halt, wenn du irgendwo
was deployst, dann machst du halt 10 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 Concurrency macht oder was die
Datensätze 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,
und Jochen unterhalten sich über die Programmiersprache Python
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. Entweder über Prozesse oder über Prozessoren,
über unterschiedliche Maschinen oder über Docker-Container,
oder über einen Kubernetes-Cluster, wo du dann halt
im Prinzip das Gleiche an ganz vielen verschiedenen Stellen
ausführst. 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 das 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 nehmen ja auch alle
AsyncIO, also die machen ja auch keine Magie.
Genau, genau, genau, aber da ging das halt
in Django ging es bisher halt noch nicht
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 AsyncViews
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-dev markiert,
also async-Funktionen hat, die Views sind und
die dann Core-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
und ja, ist halt...
Also Web-Server-Gateway-Interface und Asynchronos
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
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 Mittelbeurs-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
eine Datenbank, fragt irgendwie
ein Redis-Cache,
fragt noch irgendeine API oder sowas
und gibt dann irgendwie eine Antwort zurück
in dem 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,
erwägtet man halt.
Und
die Latenz, die man
als Client, wenn man die Seite
abfragt, zu sehen bekommt,
ist die, die der
längste I.O.
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.
Das ist ja genau das,
was du bei WebSockets brauchst. Du hast ja im Wesentlichen
einen Request, der für immer läuft.
Oder solange 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, ist,
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 irgendwann eine Antwort
zurück und dann ist das abgeschlossen.
Das ist alles, was da passiert.
Also das, was man da hinschickt, ist dann so eine Anfrage,
entweder will man irgendwie aus dem klassischen
Crudstream 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
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.
und Jochen unterhalten sich über die Programmiersprache Python
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
das klassische Beispiel ist eine Chat
Anwendung,
wo halt einer was in sein Chatfenster 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 anderes 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
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
normale HTTP-Anfrage, die
dann upgegradet 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 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 jemand was in sein Chatfenster eingetippt hat und der
Client sagt dann, bitte veröffentliche das in diesem Kanal.
Das heißt, Websoft-Grips sind so ein bisschen die
Erweiterung, nicht eine Erweiterung,
sondern eine
eine Möglichkeit,
ruhere 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 Tango?
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,
ich möchte gerne einen Websocket haben.
Und dafür gab es eben in Django diese Erweiterung, die Channel-sized,
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.
Und zwar nicht nur...
Das ist dann halt nicht...
Das sind halt Django Channels.
Also es ist quasi...
Genau, Django Channels macht halt sowas wie WebSockets,
aber halt nicht nur das, sondern auch WebRTC
und halt auch MQTT
und so.
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
Ja, also das ist das, 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 im 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
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.
Vue X.
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
dieses Phoenix macht das
halt anders. Das macht das alles auf dem
Server. Und das schickt
sozusagen nicht irgendwie
dir 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 das
JavaScript halt von dem
von diesem Liveview-Dings ist halt irgendwie so 1000 Zeilen
und ich habe einen Vortrag von dem Entwickler davon gesehen,
er 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
wenn man 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
APIs 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.
So 4-Kilobyte-Cookie-Kram, der
da hin und her geschickt wird.
und es wird jedes Mal
nochmal, auch der Server
muss immer nochmal, achso,
hier ist deine Signatur, ach du bist der User,
ach sehr gut und alles klar, ich merke mir das mal
und vergesse es sofort wieder beim nächsten Request.
Das ist halt eigentlich, wenn man sich anguckt,
was da tatsächlich passiert auf der Leitung,
das 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 nichts.
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.
Das müsste doch mal jemand machen.
Ich dachte auch schon,
vielleicht sollte man sich diese tausend
Zeilen JavaScript da mal genau
angucken und dann halt
das Ganze mit Channels und
WebSockets machen, weil
dass man den State mit Async
super handeln kann,
das kann man in Python und Django ganz genauso
machen.
das muss man nicht, 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
bevor wir aufhören können
soll ich mal einfach so W haben kooperatives Multitasking ach ja kooperatives Multitasking Genau 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?
19. Jahrhundert, oder?
Also, damals.
Also, wie Concurrency irgendwie nach Python gekommen ist.
Ich weiß nicht, ich habe das...
Ein Großteil davon habe ich aus der...
Märchen, was man seinen Kindern erzählt.
Wie Procurrency damals nach Python gekommen ist.
Ich kann nur diese Serie von
Lukas Langer über Async.io 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.
Procurrency machen.
Nebenläufig.
Und 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 Standardbibliothek-Funktionen, die blockieren alle, die machen alle
synchronen I.O. und so, das hat nie so richtig dazu gepasst, das heißt, das 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
verwendet.
Wenn man jetzt vorhatte, auf G-Event umzusteigen
oder so ging das halt nicht.
Ja,
aber Twisted ist auch ein
Riesending. Es gibt ganz viele Firmen, die
das für irgendwelche Netzwerkgeschichten benutzt haben.
Apple hat das.
Super viele Sachen, die man vorher einfach nicht machen konnte.
Genau, genau. Also es ist
schon ein Riesending.
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.
Und also Tornado und Twisted haben das beide stark beeinflusst.
Tornado auch eine ganz interessante Geschichte, ist auch ein Ding,
was Leute
geschrieben haben, oder 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
und
ja,
Brad Taylor ist dann CTO von
Facebook geworden.
Und ich hatte ja, das letzte Zufall, ich 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
tatsächlich irgendwie, ja,
der Autor von Tornado ist halt irgendwie,
war halt CTO von Facebook lange Zeit.
Und hat da wahrscheinlich auch
seine Python-Vorlieben vielleicht so ein bisschen
ausgelebt.
Jeder bringt seine eigene
Technologie mit.
Ja.
Genau.
Das
Tornado
ist auch heute noch eine ganz
interessante Geschichte. Wird auch noch
nach wie vor aktiv entwickelt.
Ist auch bei der Jupiter-Geschichte 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 irgendwann gewesen sein
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
AsyncDev 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, also 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, also
es ist aber was, es ist eine völlig andere
Geschichte
als jetzt, es gibt jetzt auch andere Sachen
also man kann zum Beispiel
Multisredding gab es in Python auch
schon immer, war in Python 2
ganz, ganz schrecklich, weil
Lochschreckliche?
Ja,
weil es tatsächlich
so ein Lock-Contention-Problem 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
Gill 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,
beziehungsweise vor Python 3.2,
dass
der Interpreter
alle 100 Ticks, also
ein Tick ist halt irgendwie so eine
ja, ich weiß nicht
Das ist ein Upcode, oder?
Ja, 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
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 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 so was wie
ja, der Python-Interpreter, der Scheduleter, irgendwas
ne, macht er nicht, das betriebssystem
aber der
Python-Interpreter kann natürlich sagen, okay, also
dieser Stretch hier wäre jetzt theoretisch runnable
der dann vom Betriebssystem
tatsächlich
sozusagen, wo der Kontext dazwischen geht und welcher dann
weiter ausgeführt wird, das macht das Betriebssystem
dann
Wie nennt man das, Jochen?
Jetzt muss ich kurz das Schlüsselwort dazwischen sagen
Präemptives Multitasking
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 wann man sie wieder bekommt
und das kann jederzeit passieren
auch in
ich habe mich da mal mit jemandem drü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 da nicht atomar, sondern
und es sind eben diese Bytecodes, die
darunter liegen, die atomar sind.
Aber so eine Zuweisung wie
i plus gleich 1
ist auch nicht atomar, sondern
das kann zwischendurch unterbrochen
werden.
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 wegnommen 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.
Also das ist
präventives Multitasking.
Präventives Multitasking, ja genau.
Hat natürlich gewisse Vorteile, aber
ist halt, also ja.
Genau, aber erstmal um das so zu, genau.
Das ist präventives und das, was man aber heute
hauptsächlich macht und was halt auch eine
gewisse Geschichte,
also auch schon immer eine Geschichte hatte,
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
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 Stacklist-Fighting 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.
LibEV hat
glaube ich
Armin Rigo geschrieben.
Was ja auch faszinierend war,
die gleichen Namen,
da tauchten viele Namen auf, die ich schon kannte.
Das sind erstaunlich wenige Leute.
Ich kannte die aus anderen Teilen,
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,
äh, nicht PyPI,
äh, 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.
Zum Beispiel das Rocketman-Rule, ganz böse.
Das ist ziemlich hart.
Sie weiß so, okay,
und Jochen unterhalten sich über die Programmiersprache Python
und kooperatives Multitasking im weitesten Sinne.
Wobei, weiß ich jetzt gar nicht, bei G-Event bin ich mir jetzt gar nicht so super sicher.
Klar, bei G-Event ist es auch kooperativ.
Ja, im Prinzip ist es kooperativ.
Im Wesentlichen jetzt ist ja AsyncIO oder so der...
Genau, das ist jetzt sozusagen der heißeste Scheiß, den man jetzt da macht.
Und ehrlich gesagt, ich habe ja jetzt da auch eine ganze Zeit lang Sachen an,
das sieht auch deutlich besser aus als alles, was man da so vorher gemacht hat.
Aber im Wesentlichen heißt es doch, jedes Mal, wenn du Yield sagst,
wird dir die Kontrolle erstmal weggenommen.
Yield? Ja, nicht, Await.
Ah, wenn du Await sagst, okay.
Ja, früher war es Yield. Ja, Yield
from, genau, das war noch die
Syntax 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 anderes 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 primitives 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. Ja, es gibt dann so kritische
Sektionen, die musst du sehr ab. Genau, und das Problem
ist halt, du darfst halt nichts vergessen und das kann
halt überall passieren und du musst halt
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, kannst du immer noch
Das ist eine Starving-Situation, es
wartet irgendjemand darauf, dass irgendwie wer losrennen
kann, aber da kommt einfach nichts.
Ne, das ist ein
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...
Schnapp, wie man vor Aspekt ist.
...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...
Ach, wäre ja so schön, 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 da halt diverse Techniken, mit denen man das halt auch, also 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 ein 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 ersetzen muss und dann Ja, aber auch da ist es erstaunlich leicht in so Situationen reinzukommen, wo du dich deadlogst
Das ist erstaunlich leicht
Jaja, 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... Urgeschichte.
Also er sagte irgendwie auf
einer, also mit einem Stride, also alles gut, mit mehreren
Strides, na, 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
das führt das 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 Texte, 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
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 eine 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
ganz gut auf Linux, also auch 10.000
Threads aufmachen, gar kein Problem
funktioniert
Genau, neulich hast du ausprobiert, Jochen
bei 9500 war Schluss bei mir
Aber
also das geht alles und das ist auch
nicht, 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 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
Betriebssystem riesig, brauchst halt
8 MB, zum Beispiel sagt Effective
Python, weil Fluid Python sind halt auch
immer in Größenordnung 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
und Jochen unterhalten sich über die Programmiersprache Python
Das heißt, das passiert, selbst wenn man ein kreatives Multitasking hat, passiert das automatisch. Also muss man sich auch nicht selber darum kümmern, sondern da gibt der Thread, der halt irgendeinen blockierenden Netzwerkaufruf gemacht hat oder I.O. Aufruf, da ist der Jill 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 man die Kontrolle
weggenommen wird und so.
Es ist im Debugging
ziemlich übel,
aber... Probleme, die wir vorhin
erzählt haben, da kommen dann halt irgendwelche Fehlermeldungen
von irgendwo her. Irgendein
Callback hat Markus 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.
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 irgendeine Kernel-Datenstruktur
um zu sagen, da bitte nicht
so, dann ist das geschützt, aber alles andere ist halt irgendwie
wilde, wilder Westen, Drachen kommen
vorbei, verbrennen einen die Hütte, also ist halt, ja, weiß man nicht
und bei Async.io ist es quasi umgekehrt, da gibt's
halt, also 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 darum kümmern, dass das halt,
dass man die Kontrolle
abgibt, wenn es geht, weil man alle anderen
blockiert, wenn man das nicht tut. Also wenn man jetzt irgendwas...
Man muss einfach kooperativ sein.
muss kooperativ sein. Wenn man irgendwas macht, was lange
dauert, dann gehen halt
alle anderen kaputt, was halt auch unter Umständen
natürlich sehr böse Konsequenzen haben kann.
Ja.
Aber da sieht man dann wenigstens. Also ich meine, wenn
du da dann den Interpreter unterbrichst, weißt du,
siehst du, wo du bist.
Wer schuld ist. Genau. Es ist auch so, dass man
kann, ich glaube,
Python-X, wenn man Debug
anschaltet und
TraceMalloc anschaltet, das sollte man immer
machen, wenn man irgendwie so Async-IO-Sachen
zumindest auf der Entwicklungsseite macht, dann
ist, sollte man das mal anschalten.
Produktion natürlich unter Umständen
nicht, kostet auch Ressourcen, aber
dann sagt einem der Interpreter zum Beispiel
sowas wie, also hier hast du
irgendwie ein Task oder was, diese Funktion
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.
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 Coroutine 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 davorsteht
und alles andere ist halt sozusagen ganz
normaler Python-Code eigentlich.
Ja.
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
also es ist, ich weiß
es geht hier hinten ins Fetz auch
aber natürlich ist es auch so, dass die sind schon
Ressourcen aufwendiger, also
das habe ich jetzt nicht nachvollzogen
aber also Coroutine 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
Zehn, Hunderttausende davon haben, kein Ding.
Du musst halt bloß
schnell genug bleiben, dass du halt tatsächlich,
dass diese Hunderttausende auch irgendwann alle mal wieder drankommen,
aber ansonsten geht das.
Und ja, da gibt es ja dann auch
sehr schnelle Event-Clubs drunter, also man kann
halt auch, es gibt die Referenz-Implementation,
der Event-Club in
Python, die ist nicht schnell,
aber die ist halt dafür da, damit man weiß,
wie es funktioniert.
Wenn man jetzt eine andere Implementation schreibt, die auch
dagegen testen kann und 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,
also Leap UV
und das ist die Node.js Event-Loop und die ist halt
echt sackschnell.
Damit möchte man halt unter Python
quasi da auch dann die gleiche Geschwindigkeit
hin.
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.
Einmal Awave machen.
Yield.
Ich würde einmal Yield sagen
und dann direkt Sleep aufrufen.
Das ist doch ein sehr schönes Stichwort, oder?
Ja. Aber es hört sich für mich
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. 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.
Es ist wirklich schwer.
Es ist auch eine massive Fehlerquelle.
Ich finde es auch
wirklich
und
und ich sage, passiert mir nichts.
Und das nimmt ganz, ganz, ganz viele
von diesen Ecken und Kanten da raus,
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...
Ob ich es geplant hätte.
Ja, würde ich sagen, machen wir doch einfach...
Ja, an dieser Stelle, bleibt uns gewogen,
wenn 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.
Ja,
schön, dass ihr wieder eingestaltet habt.
Alle Kritik, Feedback und so weiter,
bis zum nächsten Mal. Tschüss.
Bis dann. Tschüss.