11 Punkte von dalinaum 2023-03-03 | 4 Kommentare | Auf WhatsApp teilen

Das Empfehlungsteam von Kakao entwickelt eine neue Plattform als Ersatz für die bestehende Machine-Learning-Plattform.

Mit Python, der Hauptsprache des Teams, war es etwas schwierig, bei der Anwendung sowohl Performance als auch Sicherheit gleichermaßen sicherzustellen.

Für eine Anwendung mit Nutzerkennzahlen wurde Rust eingeführt, um zu prüfen, ob es angemessen ist, Anwendungen in Rust zu implementieren.

  • Rust verarbeitete Aufgaben etwa 1,9-mal schneller als Python
  • Beim Speicherverbrauch nutzte Python etwa 4,5-mal mehr als Rust
  • Die CPU-Auslastung von Python war gegenüber Rust bis zu 3-mal, im Durchschnitt etwa 2-mal höher
  • Da Python asyncio und Rust tokio jeweils in den Anwendungen der beiden Sprachen eingesetzt wurden, war selbst in einer Single-Thread-Umgebung mit identisch implementierter asynchroner Verarbeitung die Nachrichtenverarbeitung in Rust etwa 10-mal schneller als in Python

Einer der größten Nachteile von Rust war der hohe Lernaufwand.

Auch bei der Entwicklung mit Python wurden Typannotationen verpflichtend verwendet. Während die Anwendung für Nutzerkennzahlen in zwei Versionen implementiert wurde, wurde der Unterschied in der Entwicklungszeit zwischen Python und Rust nicht als besonders groß empfunden.

Der größte wahrnehmbare Unterschied bei der Produktivität war die Kompilierzeit. (einschließlich Paket-Download- und Docker-Zeit)

  • Rust lag bei ungefähr 340 Sekunden
  • Python lag bei ungefähr 100 Sekunden

In Python haben Daten, die von Bibliotheken ohne Typinformationen erzeugt werden, den Typ Any, bei dem die Typprüfung ignoriert wird. Das verringert die Genauigkeit der Typprüfung im gesamten Projekt.

Es gab außerdem Unterschiede wie die Verwendung von Exceptions in Python und des Enum-Typs Result in Rust.

Entwicklungstools
Im Fall von Rust bietet cargo standardmäßig viele Funktionen.
Python-Entwicklungstools sind weit fortgeschritten und nach der Installation vergleichsweise einfach zu nutzen.

4 Kommentare

 
jongpak 2023-03-03

Ich habe zwar weder mit Python noch mit Rust Erfahrung, aber wenn ich nur den Artikel betrachte, erkenne ich keinen großen Vorteil bei der Einführung von Rust.

Nicht, dass Rust schlecht wäre, aber auch die Experimente, die für die Einführung von Rust durchgeführt wurden, wirken dürftig.
(Wenn man nur das Ergebnis der Verarbeitung von gerade einmal 50 Nachrichten betrachtet und daraus ableitet, dass etwas um ein Mehrfaches schneller und deshalb um ein Mehrfaches besser sei, finde ich diese Argumentation ziemlich schwach.)

Außerdem wurde nicht einmal mit derselben Verarbeitungslogik verglichen (synchron vs. asynchron).
[Python-Bibliothek, die asynchrone Nachrichtenverarbeitung unterstützt, aber kaum Referenzen hat] vs. [Rust als Sprache mit hoher Lernkurve und dem Risiko der Wartung durch nur wenige Personen]
Wenn man diese beiden Situationen betrachtet, frage ich mich auch, ob der Aspekt der langfristigen Nachhaltigkeit wirklich ernsthaft durchdacht wurde (zumindest wirkte es im Artikel nicht so).

Gerade bei ETL muss man vermutlich oft kurz und häufig testen; da erscheinen mir Build-Zeiten von 100 Sekunden vs. 300 Sekunden als erheblicher Flaschenhals in der Entwicklung.
Im Artikel wird zwar erwähnt, dass Incremental Builds hervorragend seien, aber dieser Punkt wird dann nur per Hyperlink abgehandelt ...

In der Praxis wurde vermutlich gründlich recherchiert und geprüft, aber zumindest nach dem Eindruck, den der Artikel vermittelt ... was sich durch die Einführung von Rust tatsächlich verbessert hat, welcher erwartete Nutzen besteht und welches Problem dadurch gelöst wurde, ist für mich weder erkennbar noch leicht nachzuvollziehen.


Persönlich habe ich schon oft gesehen, dass Technologien wegen einer „gerade angesagten Technik“ oder für eine Zeile im Lebenslauf ausgewählt wurden, und am Ende konnten sie im Team nicht einmal vernünftig gewartet werden und blieben meist als technische Schulden zurück.

  • Zum Beispiel, wenn behauptet wird, man müsse unbedingt Kafka oder asynchrone Verarbeitung einsetzen, obwohl die Workload klein ist und selbst sequentielle Verarbeitung überhaupt kein Problem wäre
  • Oder wenn etwas im Bereich asynchrone Verarbeitung als besonders gut angepriesen und ohne Rücksicht auf die Teamsituation eingeführt wird, Troubleshooting dadurch extrem schwierig wird und am Ende nur ein weiteres Legacy-System entsteht ...
  • Oder wenn es heißt, die Einführung des aktuell gehypten ooo bringe große Vorteile, nur damit kurz darauf wieder ein anderes angesagtes ooo auftaucht und dann dieses als die bessere Wahl dargestellt wird ...

Natürlich will ich nicht sagen, dass das bei diesem Rust-Artikel genauso ist, und ich hoffe auch, dass es nicht so ist.
Aber nachdem ich mehrfach erlebt habe, dass letztlich die Teammitglieder unter Technologien leiden, die ohne ernsthafte Überlegungen eingeführt wurden, lese ich solche Technik-Promotion-Artikel wohl mit größerer Vorsicht.

 
ehlegeth 2023-03-03

Grundsätzlich wirkt das wie eine ETL-Task. Wurde in dieser Domäne auch Java in Betracht gezogen, das zusammen mit Python Stärken hat, und falls es im Vergleich zu Rust bewusst ausgeschlossen wurde, würde mich der Grund dafür interessieren.

 
kayws426 2023-03-03

Es ist schade, dass einige Vergleichsdaten zur Performance aus kleinen Tests stammen.

 
ehlegeth 2023-03-03

Die Aussagekraft von Performance-Tests verändert sich je nach Charakter der Workload erheblich, daher ist es etwas schade, dass es keine Erläuterungen dazu gibt, wie das Testdesign aussah oder wie die Zahlen ermittelt wurden.
Zum Beispiel würde mich interessieren, ob nach der Verarbeitung von 5 Millionen Fällen auf Basis von 50 Fällen ein arithmetischer Mittelwert gebildet wurde, und falls ja, wie dann der Speicherverbrauch bestimmt wurde oder wie die Unterschiede bei der CPU-Auslastung gemessen wurden. (Bei der Zeit ist vermutlich die wall-clock time gemeint?)
Außerdem gibt es die Interpretation, dass „beim Blick auf die CPU-Auslastung der Großteil des Performance-Unterschieds zwischen den beiden Sprachen aus I/O-Aufgaben stammt, nämlich dem Konsum von Kafka-Nachrichten und dem Speichern von MongoDB-Dokumenten“. In den Ergebnissen hieß es jedoch, die wall-clock time von Rust habe etwa die Hälfte betragen und die CPU-Auslastung (CPU time?) ein Viertel bis ein Fünftel. Daher ist für mich nicht ganz klar, ob damit Unterschiede in der Implementierungsweise rund um I/O gemeint sind oder Unterschiede bei der Verarbeitung CPU-intensiver Daten, die mit I/O-Zielen zusammenhängen. Die Logik ist für mich an dieser Stelle etwas schwer nachzuvollziehen. Dass Rust bei CPU-intensiven Tasks Vorteile hat, ist schließlich allgemein bekannt; falls Letzteres gemeint ist, scheint es eigentlich gar nicht nötig zu sein, Unterschiede bei Bibliotheken eigens zu erwähnen. Wenn es im Experiment tatsächlich um einen CPU-intensiven Workload ging, hätte der Unterschied vielmehr deutlich größer ausfallen müssen, ähnlich wie beim im Artikel erwähnten Vergleich der Implementierungen mit asyncio und tokio. Daher würde ich es eher so interpretieren, dass der Performance-Unterschied wegen des I/O-Anteils geringer ausgefallen ist.