{"id":11375,"date":"2022-01-13T13:37:45","date_gmt":"2022-01-13T11:37:45","guid":{"rendered":"http:\/\/www.soeren-in-norwegen.net\/blog\/?p=11375"},"modified":"2021-09-01T11:32:46","modified_gmt":"2021-09-01T09:32:46","slug":"kevin-bacon-xiii-size-matters","status":"publish","type":"post","link":"http:\/\/www.soeren-in-norwegen.net\/blog\/2022\/01\/kevin-bacon-xiii-size-matters\/","title":{"rendered":"Kevin Bacon &#8211; XIII &#8211; Size Matters!"},"content":{"rendered":"<p><a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/?p=11047\" target=\"_blank\" rel=\"noopener\">Beim letzten Mal<\/a> beschrieb ich die Umwandlung des urspruenglichen Sprachproblems in ein mathematisches Problem. Damit kann man prinzipiell so wie&#8217;s ist (von <em>Apfel<\/em> zu <em>Kuchen<\/em> zu <em>Mehl<\/em> usw.) an die Sache heran gehen.<br \/>\nWir sprechen hier aber von fast 6 Millionen Knoten (Wikipediatiteln) und mehr als 181-Millionen Verbindungen dazwischen in diesem Netzwerk. Und fuer jeden Knoten muss ich die Gesamtheit der Verbindungen &#8222;abschreiten&#8220;. Dabei lief ich in ein albekanntes Problem: nicht genug Speicher! Aber der Reihe nach.<\/p>\n<p><a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/2021\/08\/kevin-bacon-vii-dead-links-walking\/\" target=\"_blank\" rel=\"noopener\">Vor ein paar Monden<\/a> h\u00f8rte ich mit der Saeuberung der Rohdaten auf und es blieben noch \u2026<\/p>\n<blockquote><p>[\u2026] 5,798,312 Wikipediaseiten auf denen insgesamt 165,913,569 Links erscheinen [\u2026]<\/p><\/blockquote>\n<p>\u2026 zurueck.<\/p>\n<p>Ich schrieb auch, dass der Speicherbedarf dieser Daten von ehemals ueber 70 GB (die gesamte Wikipedia) auf 4.1 GB verringert wurde. Ich hatte das auf 61 Dateien verteilt und die bin ich fuer die bereits vorgestellten Untersuchungen immer der Reihe nach durchgegangen (denn da hat mich ja das Netzwerk an sich nicht interessiert).<br \/>\nDas Komische war nun, dass das eigentlich alles in den Speicher meines Laptops passen sollte \u2026 aber irgendwie kam dieser nicht zurecht, wenn ich versuchte mehr als 10 dieser Dateien gleichzeitig zu laden.<\/p>\n<p>Merkwuerdig \u2026 wie sieht das denn eigentlich im Speicher aus?<br \/>\nNunja, erstmal dachte ich ganz einfach, dass die Titel der Seiten Buchstabenketten (allgemeiner: Zeichenketten) mit einer bestimmten Laenge sind. Dito bzgl. der Links &#8222;hinter&#8220; jedem Titel.<br \/>\nIm Wesentlichen braucht ein Buchstabe im Speicher 1 Byte \u2026 jaja, Sonderzeichen brauchen mglw. mehr, aber ich sollte davon nicht soooo viele haben \u2026 Der Speicherbedarf der Titel sollte also das Integral ueber die <a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/2021\/08\/kevin-bacon-viii-titelspielereien-c-das-ist-doch-nicht-normal\/\" target=\"_blank\" rel=\"noopener\">hier gezeigte Verteilung<\/a> sein: 117,194,976 Bytes also ca. 117 MB.<br \/>\nDie Verteilung der Laengen der Links ist sehr aehnlich:<\/p>\n<p><a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-content\/uploads\/35_Verteilung_Laenge_Links_und_Titel_.png\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-11395 size-full\" src=\"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-content\/uploads\/35_Verteilung_Laenge_Links_und_Titel_.png\" alt=\"\" width=\"573\" height=\"453\" \/><\/a><\/p>\n<p>In den nicht normierten Daten ist die Amplitude der Verteilung der Links natuerlich viel gr\u00f8szer und diese muss natuerlich fuer das Integral genommen werden.<br \/>\nNebenbemerkung: das kleine &#8222;Uebergewicht&#8220; bzw. &#8222;Untergewicht&#8220; links bzw. rechts vom Maximum ist sicherlich dadurch zu erklaeren, dass &#8222;prominente&#8220; (also oft zitierte) Seiten einen kurzen und knackigen Titel haben &#8212; <a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/?p=10914\" target=\"_blank\" rel=\"noopener\">siehe hier<\/a>. Der Unterschied ist zwar zu sehen, aber nicht so massiv (oder unerwartet), sodass ich mich da nicht weiter fuer interessiere. Insb. auch deswegen nicht, weil die gegebene Erklaerung (mit den Beispielen der meistzitierten Seiten) durchaus plausibel klingt.<\/p>\n<p>Fuer den Speicherbedarf aller in den Links enthaltenen Zeichen errechnete ich nun: 2,898,076,329 also ca. 2.9 GB.<\/p>\n<p>Na sowas! Meine simplen Ueberlegungen l\u00f8sen die Merkwuerdigkeit nicht auf!<br \/>\nDes Raetsels L\u00f8sung ist zweigeteilt und ich gebe zu, dass das ueber das Anfaengerprogrammiererniveau hinaus geht (wenn auch nicht sehr weit). Aber dafuer muss ich etwas ausholen. Das wiederum handelt im vorbeigehen auch gleich etwas ab, was beim naechsten Mal total hilft :) .<\/p>\n<p>Nehmen wir die Zeichenkette &#8222;gerader Strich mit kurzer Kappe, zwei mal zwei nach links offene Halbkreise, schraeger Strich mit Vordach&#8220; &#8212; oder in kurz 1337.<br \/>\nIch nehme 1337 mit Absicht. Zum Einen ist es natuerlich die Zahl Eintausenddreihundertsiebenundreiszig. Dann es aber auch das bekannteste Beispiel fuer <a href=\"https:\/\/en.wikipedia.org\/wiki\/Leet\" target=\"_blank\" rel=\"noopener\">Leetspeak<\/a> und wird eben auch direkt als &#8222;LEET&#8220; &#8212; also ein Wort &#8212; interpretiert.<br \/>\nEin und die selbe (!) Zeichenkette hat also zwei unterschiedliche Bedeutungen. So wir denn von diesen Unterschieden wissen, so ist das fuer uns Menschen i.A. kein Problem 1337 kontextabhaengig richtig zu interpretieren. Wenn ich also sage packe bei 1337 nochmal 1337 ran, so ist das eine Addition im Falle der Zahl und das Ergebnis wird 2274 bzw. wird is im Falle des Wortes 13371337 (also LEETLEET).<\/p>\n<p>Damit bin ich bei einem weiteren wichtigen Aspekt: Operationen.<br \/>\nAbhaengig von der Bedeutung die die Zeichenkette hat, kann man damit unterschiedliche Operationen ausfuehren oder gleiche Operationen, die aber unterschiedliche Ergebnisse haben. Oben erwaehnte ich die Addition. Eine andere Operation waere &#8222;Sag mir mal die Laenge von dem was ich gerade vor mir habe&#8220;.<br \/>\nBei LEET entspricht die Laenge natuerlich der Anzahl der Zeichen und ist somit vier. Aber selbst wenn eine Zahl viele Zahlzeichen enthaelt, so ist die Laenge einer Zahl doch immer eins! Das ist besser zu verstehen, wenn man r\u00f8mische Zahlsymbole nimmt, denn da sind 10, 50, 100, 500 und 1000 nur ein Symbol. Noch cooler ist das <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cistercian_numerals\" target=\"_blank\" rel=\"noopener\">cistercianische Zahlsystem<\/a>, welches bis 9999 immer nur ein Symbol braucht.<\/p>\n<p>Das alles weisz man &#8222;automatisch&#8220; als Mensch, aber dem Computer muss man zu jeder Zeichenkette sagen, was die jetzt eigentlich fuer eine Bedeutung hat, damit die richtigen Operationen drauf ausgefuehrt werden. Und hat eine Zeichenkette erstmal eine Bedeutung, so aendert die sich niemals \u2026 \u2026 \u2026 jaja, ich weisz, dass es da Spezialfaelle gibt, die Ausnahmen zu dieser Aussage sind \u2026 aber mir geht&#8217;s hier darum, dass man einem Computer explizit und jedes Mal sagen muss, womit dieser eigentlich gerade arbeitet.<br \/>\nDas ganze geht natuerlich noch viel tiefer direkt rein in die Innereien des Computers. Denn eine Zahl ist im Speicher ganz anders dargestellt als ein Wort.<\/p>\n<p>Worauf ich hinaus will ist das Folgende. Jedes Objekt im Program (also meine Zeichenketten) hat &#8222;Betriebskosten&#8220; in Form von Speicherplatzbedarf wo eben die Bedeutung des besagten Objektes abgelegt ist. Diese &#8222;Betriebskosten&#8220; beinhalten das was ich oben sagte, damit der Computer weisz, wie mit besagten Objekten umzugehen ist. Interessiert bin ich aber nur an der &#8222;Ladung&#8220; eines Objektes; also der Zahl oder dem Wort an sich. Diese &#8222;Ladung&#8220; kommt zu den &#8222;Betriebskosten&#8220; hinzu.<\/p>\n<p>Um die &#8222;Betriebskosten&#8220; kommt man niemals drumherum und es gibt nun zwei M\u00f8glichkeiten, wie man das handhaben kann. Zentral oder dezentral.<br \/>\nZentral bedeutet, dass man eine gewisse Menge Speicherplatz reserviert und ranschreibt welche Bedeutung alle Objekte die sich darin befinden haben. Dann muss man das nur einmal sagen und die &#8222;Betriebskosten&#8220; fallen nur einmal an.<br \/>\nDezentral bedeutet, dass man das an jedes einzelne Objekt ranschreibt. Dann fallen die &#8222;Betriebskosten&#8220; fuer jedes Objekt an. Warum sollte man das machen? Naja, dafuer gibt es technische Gruende, und mindestens einen eher philosophischen Grund: um dem Menschen der das Programm schreibt die Arbeit zu erleichtern. Denn das ist genau das was Python macht. Speicher- und Objektmanagement sind Dinge, die man in anderen Programmiersprachen explizit machen muss. Ich finde das durchaus interessant, aber ich gebe zu, dass es vom eigentlichen Programmieren (sich logische Strukturen ueberlegen, die ein gewisses Problem l\u00f8sen) abhaelt, wenn man das &#8222;Inventar&#8220; immer &#8222;sortieren und sauber halten&#8220; muss.<\/p>\n<p>Und das ist das was ueber das Anfaengerprogrammiererniveau zumindest unter Python hinausgeht. &#8222;Anfaengerprogrammiererniveau&#8220; deswegen, weil Python heutzutage nunmal die Sprache ist, in der mglw. die allermeisten Leute anfangen zu programmieren. Und die fangen damit an, eben weil da solche Sachen im Hintergrund passieren\u00a0 und vom Menschen der den Code schreibt weg gehalten werden.<br \/>\nEs ist aber natuerlich auch Grund, warum Python nicht fuer die Programmierung wirklich groszer Programme (wie bspw. Betriebssysteme) benutzt wird. Hat halt alles seine Vor- und Nachteile.<\/p>\n<p>Soweit dazu. Den Speicherbedarf der &#8222;Ladung&#8220; habe ich oben berechnet. Aber wie grosz sind denn nun die &#8222;Betriebskosten&#8220; pro Zeichenkette? Nun ja, das ist kompliziert und nicht nur von der Architektur des Rechners und Betriebssystems, sondern auch der benutzten Inkarnation der Programmiersprache abhaengig. Unter Python 3.7.3 auf meinem Rechner belaufen sich besagte &#8222;Betriebskosten&#8220; von Zeichenketten auf 49 Byte pro Objekt. (Unter Python 2.7.16 sind es uebrigens nur 37 Byte).<br \/>\nDa wir 5,798,312 Wikipediaseiten und 165,913,569 Links haben kommen zu den obigen ca. 3 GB also nochmals 8,413,882,169 Byte hinzu. Eigentlich ein bisschen mehr, weil Sonderzeichen h\u00f8here &#8222;Betriebskosten&#8220; haben, aber in der Summe sind das dann ungefaehr 11 GB.<\/p>\n<p>Mhm \u2026 11 GB das wird zwar knapp, aber so viel habe ich eigentlich. Warum kommt der Computer aber schon nicht mehr klar, wenn ich nur 10 Dateien eingelesen habe?<br \/>\nOhne lange Rede: die Links sind in Sets (das ist sowas wie &#8217;ne Liste ohne doppelte Objekte) angeordnet und davon habe ich natuerlich pro Titel eins. Insgesamt ist dann alles in einem einem sogenannten &#8222;Dictionary&#8220; sortiert, damit ich zu jedem Titel leicht die zugeh\u00f8rigen Links finde (wie eben in einem Lexikon). Solche uebergeordneten Strukturen haben natuerlich auch Betriebskosten zusaetzlich (!) zu denen der einzelnen Elemente die in diesen Strukturen &#8222;aufbewahrt&#8220; werden. Aber anders als bei den &#8222;primitiven&#8220; Objekten wie oben beschrieben steigen die Betriebskosten in Abhaengigkeit von der Anzahl der Elemente die sich darin befinden. Klar, der gesamte Speicherbedarf eines Wortes ist abhaengig von der Anzahl der Buchstaben, aber das ist die &#8222;Nutzlast&#8220;. Die &#8222;Betriebskosten&#8220; des Wortes sind davon unabhaengig. Und das ist bei den uebergeordneten Strukturen anders (weil die komplizierter sind und auch kompliziertere Operationen erlauben).<\/p>\n<p>Zur besseren Veranschaulichung stelle man sich einen Gueterzug der Farbe transportiert vor. Alle Links die zu einem Titel geh\u00f8ren entsprechen einer Farbe. Besagte Sets sind dann ein Tankwaggon, die jeweils nur eine Farbe enthalten. Wenn ich mehrere Tankwaggons habe, dann fallen die Betriebskosten (Wartung, oder Versicherung) pro Stueck an. Habe ich weniger Farbe, benutze ich einen kleineren Tankwagon, der geringere Kosten hat. Die Lokomotive (welche wiederum Betriebskosten hat) nun zieht alle Tankwaggons. Habe ich nur ein paar, benutze ich eine kleinere Lokomotive (mit geringeren Kosten), als wenn <a href=\"https:\/\/en.wikipedia.org\/wiki\/Trans-Siberian_Railway#\/media\/File:VL_85-022_container_train.jpg\" target=\"_blank\" rel=\"noopener\">der Gueterzug so lang ist wie in Sibirien<\/a>.<\/p>\n<p>Und der Speicherbedarf dieser uebergeordneten Strukturen entwickelt sich selbst ohne die &#8222;Nutzlast&#8220; dramatisch! Die &#8222;Waggons&#8220; in denen sich die Links befinden ben\u00f8tigen in ihrer kleinsten Form (also ohne Nutzlast, wenn ein Titel keine Links enthaelt) bereits 224 Bytes. Bei den ca. 6 Millionen Titeln macht das also mindestens (!) nochmal 1.3 GB. Und nun kommen wir in Regionen, wo mir der Speicher ausgeht.<\/p>\n<p>Aber eigentlich braucht die Anordnung in Sets deutlich mehr, denn beim Maximum der <a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/?p=11079\" target=\"_blank\" rel=\"noopener\">Verteilung bzgl. der Anzahl der Links pro Titel<\/a>, beansprucht ein Set bereits 736 Bytes Speicherbedarf an &#8222;Betriebskosten&#8220;. 736 Bytes braucht ein Set auch dann, wenn es 18 Elemente hat, aber ab 19 Elementen braucht es 2272 Bytes. Insgesamt sieht das dann so aus:<\/p>\n<p><a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-content\/uploads\/36_Speicherbedarf.png\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-11386 size-full\" src=\"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-content\/uploads\/36_Speicherbedarf.png\" alt=\"\" width=\"579\" height=\"454\" \/><\/a><\/p>\n<p>Puuuuh \u2026 das geht linear, nochmal Glueck gehabt \u2026 \u2026 \u2026 Oopsie, das sind ja <a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/?p=11040\" target=\"_blank\" rel=\"noopener\">doppeltlogarithmische Achsen<\/a>! \u2026 \u2026 \u2026 Ach du meine Guete! Der Anstieg ist ja positiv! Damit wird ja der Exponent des maechtigen Gesetzes gr\u00f8szer Null!<\/p>\n<p>Lange Rede kurer Sinn: die vormals betrachtete, oben verlinkte, Verteilung der Anzahl der Links fuer alle Titel muss mit dem hier dargestellten Speicherbedarf _multipliziert_ werden. Das sieht dann so aus:<\/p>\n<p><a href=\"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-content\/uploads\/37_realer_Speicherbedarf_aller_Sets.png\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-11387 size-full\" src=\"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-content\/uploads\/37_realer_Speicherbedarf_aller_Sets.png\" alt=\"\" width=\"613\" height=\"456\" \/><\/a><\/p>\n<p>Mist! Die Ordinate ist linear und in Megabyte.<\/p>\n<p>Erst jetzt ergibt das Integral unter dieser Kurve den tatsaechlichen Speicherbedarf dieser Ueberstruktur von Sets welche besagte Links enthalten: 10,962,695,936 Byte also ca. 11 GB die zu den obigen 11 GB noch dazu kommen. So viel Speicher habe ich nicht. Die &#8222;Lokomotive&#8220; (das &#8222;Dictionary&#8220;), also die oberste Ordnungsstruktur, braucht dann bei ca. 6 Millionen Elementen nochmals 300 MB. Aber das faellt dann kaum mehr ins Gewicht.<\/p>\n<p>Ich fasse zusammen. Der Speicherbedarf der eigentlichen &#8222;Buchstaben&#8220; aller Titel und Links betraegt nur 3 GB. Aber die Verwaltung all dieser Buchstabenobjekte verursacht (in Python) &#8222;Betriebskosten&#8220; von 8 GB. Die Strukturen in der die ganzen Objekte nun zusammengefasst sind verursacht dann nochmals &#8222;Betriebskosten&#8220; in H\u00f8he von weiteren 11 GB.<br \/>\nKein Wunder, dass mein Computer da keine Lust drauf hat.<\/p>\n<p>Wie ich dieses Problem l\u00f8ste stelle ich beim naechsten Mal vor. Denn die L\u00f8sung ist echt cool (weil so elegant) und erlaubte mir ueberhaupt erst das Gesamtproblem (die Erforschung des Linknetzwerkes) derart umzuformulieren, dass ein Computer das (schnell) l\u00f8sen konnte.<\/p>\n<p>Ach so \u2026 wenn ich hier 22 GB zusammenrechne, wie komme ich denn auf die 4.1 GB, die ich ganz oben erwaehne. Nun ja, wenn ich das alles auf der Festplatte speichere, dann wird die Struktur <a href=\"https:\/\/en.wikipedia.org\/wiki\/Serialization\" target=\"_blank\" rel=\"noopener\">serialisiert<\/a>. Dabei werden strukturierte Daten in einen seriellen Datenstrom &#8222;umgewandelt&#8220; fuer die Speicherung. Darauf kann ich dann natuerlich nicht arbeiten.<br \/>\nIch k\u00f8nnte mir denken, dass viele von den &#8222;Betriebskosten&#8220; gespart werden k\u00f8nnten, indem man einen Teil des seriellen Datenstroms bspw. als &#8222;ab hier keine Zahlen sondern nur W\u00f8rter&#8220; definiert (anstatt das fuer jedes Wort einzeln zu machen). Wenn das wieder zurueck &#8222;uebersetzt&#8220; (de-serialisiert) wird, dann sieht der Algorithmus das und &#8222;baut&#8220; daraus die richtigen Wortobjekte.<br \/>\nAber das sollte alles als Spekulation gesehen werden, denn ich habe eigentlich gar keine Ahnung was da wirklich passiert.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Beim letzten Mal beschrieb ich die Umwandlung des urspruenglichen Sprachproblems in ein mathematisches Problem. Damit kann man prinzipiell so wie&#8217;s ist (von Apfel zu Kuchen zu Mehl usw.) an die Sache heran gehen. Wir sprechen hier aber von fast 6 Millionen Knoten (Wikipediatiteln) und mehr als 181-Millionen Verbindungen dazwischen in diesem Netzwerk. Und fuer jeden [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/posts\/11375"}],"collection":[{"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/comments?post=11375"}],"version-history":[{"count":9,"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/posts\/11375\/revisions"}],"predecessor-version":[{"id":11397,"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/posts\/11375\/revisions\/11397"}],"wp:attachment":[{"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/media?parent=11375"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/categories?post=11375"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.soeren-in-norwegen.net\/blog\/wp-json\/wp\/v2\/tags?post=11375"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}