Im Grunde kann man alle Probleme durch synchrone und sequenzielle Verarbeitung lösen. Das dauert dann manchmal zwar ein wenig, aber es geht. So bringt es uns auch jeder Programmierkurs bei. Ein Befehl folgt auf den anderen. Ein Unterprogramm ruft das nächste und wartet auf dessen Ergebnis, bevor es selbst weitermacht. Unterprogramme sind insofern fast nur syntactic sugar, denn ihr Code könnte auch am Aufrufort eingesetzt stehen. Compiler tun auch genau das, wenn es ihnen angemessen erscheint. Das heißt dann Inlining.
Was aber, wenn so eine sequenzielle Verarbeitung zu langsam ist? Na, dann macht man sie halt schneller, indem man den Algorithmus verbessert (z.B. Quick Sort statt Bubble Sort) oder einen schnelleren Prozessor kauft. Das ist dann so, als würde man einen schmächtigen Maurer ins Fitnessstudio schicken, damit er in Zukunft schneller Steine schleppen kann. Oder man ersetzt ihn gleich durch ein Förderband.
Wie effizient kann eine Implementation aber werden? Irgendwann ist der beste sequenzielle Algorithmus implementiert. Wie schnell können Prozessoren werden? Irgendwann ist da eine physikalische Grenze erreicht - wie es gerade so um die 3-6 GHz zu sein scheint. Genauso ist es mit der Kraft bei Maurern und der Schnelligkeit von Föderbändern. Da gibt es einfach ein Ende der Fahnenstange. Dann hilft nicht mehr Quantität. Nein, dann muss sich die Qualität ändern.
Angekommen ist das in der Programmierausbildung aber eher noch nicht, würde ich sagen. Denn es herrscht immer noch das Denken in synchronen und sequenziellen Abläufen vor, die man eben versucht durch quantitative Einflussnahme zu beschleunigen. Weniger Instruktionen oder schnellere Prozessoren stehen als Wunschvorstellung hinter den Klagen darüber, dass mal wieder der Aufbau eines Fensters zu lange dauert oder die Datenbank zu langsam ist.
Dabei wussten schon die alten Ägypter, dass man Pyramiden nicht schneller baut, indem man die Arbeiter erstmal ins Bodybuilding-Studio schickt. Die Pyramiden wurden von normalen Einwohnern Ägyptens gebaut. Genauso wie der Otto Versand vor allem Durchschnittsmenschen zur Bewältigung aller durch Menschen durchzuführenden Tätigkeiten einstellt. Sowohl die Ägypter wie der Otto Versand müssen halt damit leben, dass es vor allem normale Menschen gibt. Das liegt in der Definition von normal. Exzeptionelle Menschen - besonders starke, schnelle oder kluge - gibt es nur vergleichsweise wenige. Man kann sie daher nicht in größerer Menge rekrutieren und schon gar nicht bezahlen.
Die Lösung für Geschwindigkeitsprobleme liegt daher nicht im scale-up, in der Effizienzsteigerung von etwas Einzelnem, d.h. einem Arbeiter, einem Förderband, einem Rechner.
Die wahre Lösung liegt vielmehr in der Parallelisierung. "Normale" Ressourcen gleichzeitig an einer Aufgabe arbeiten zu lassen - z.B. viele normale Ägyptische Bauern an einer Pyramide oder Hamburger Bürger beim Otto Versand -, ist letztlich der weiter führende Weg, um dauerhaft schnell zu sein.
Beim scale-out stehen viele billige Ressourcen nebeneinander und arbeiten parallel an der Bewältigung einer Gesamtaufgabe. Statt viel Zeit in die Optimierung von Algorithmen zu stecken oder viel Geld in eine noch schnellere Hardware, sollten Sie überlegen, inwiefern die abzuarbeitenden Schritte in Ihrer Software parallelisierbar sind.
Das geht nicht, glauben Sie, weil Sie keine riesige ERP-Software für komplexe Geschäftsprozesse schreiben? Sie entwickeln doch nur ein kleines CRM - bei dem allerdings der Programmstart und auch der Wechsel zwischen Bearbeitungsmaske und Suchdialog an Performance zu wünschen übrig lassen.
Aber warum soll den nicht auch in solcher Software, die scheinbar nur aus sequenziellen, synchronen Verarbeitungsschritten besteht, etwas Parallelität möglich sein?
- Beispiel Programmstart: Alles, was beim Programmstart nicht visuell ist (z.B. das Laden von Lookup-Daten), kann parallel zur Anzeige eines ersten Dialogs im Hintergrund passieren.
- Beispiel Suchen: Abfragen können im Hintergrund laufen, während das User Interface weiterhin bedienbar bleibt. Abfrageergebnisse können häppchenweise ans UI geliefert werden; niemand sollte darauf warten müssen, dass auch noch der tausendste Datensatz dem Grid hinzugefügt ist, bevor er weiterarbeiten kann.
- Beispiel Bearbeitungsende: Wenn am Ende der Bearbeitung Daten zu speichern sind, dann kann das parallel zur weiteren Bedienung geschehen. Warum sollte ich als Anwender darauf warten, dass die Daten auch vollständig und korrekt in der Datenbank angekommen sind? Das ist doch selbstverständlich.
Falls Sie diese Beispiele nicht überzeugen, biete ich an, dass ich Ihre Anwendung daraufhin untersuche, wo es Parallelisierungspotenzial gibt. Ich bin sicher, da gibt es einiges zu entdecken.
Warum nutzen wir das große scale-out Potenzial denn aber nicht in unseren Anwendungen? Gelegentlich mag es daran liegen, dass sich ein Algorithmus nicht so leicht parallelisieren lässt. Das halte ich aber für ein Detailproblem. Vor allem sehe ich den Grund nämlich in einem Mangel an 1. Bewusstsein und 2. einfacher (!) Technologie.
Sie können Programmteile heute selbstverständlich parallel machen. Asynchronizität ist natürlich möglich. Aber sie ist trotz aller Bemühungen der .NET-Framework-Entwickler noch nicht wirklich, wirklich einfach. Auch sind die Lösungen verteilt: ein bisschen steckt in System.Threading, ein bisschen in der CCR, ein bisschen in WCF usw.
Ich halte daher eine Konsolidierung für geboten. Das, was an Technologieschnipseln vorhanden ist, sollte unter einem intuitiven, einfach einzusetzenden Dach zusammengefasst werden. Dazu müsste dann aber wohl noch etwas Theorie kommt. Wir müssen Software erstmal aus grundsätzlich asynchronen Bausteinen zusammengesetzt denken.
Aber ich sehe Licht am Horizont... :-) Mit einem Architekturansatz wie "Systemorientierten Programmierung" (SOP) und einer Zusammenführung von DI Frameworks mit Enterprise Service Bus (ESB) und Space Based Computing/Architecture (SBC/SBA) könnte es besser werden. Bei SOP stehen Softwarezellen als asynchrone und verteilte Codeeinheiten am Anfang, so dass das Denken in Richtung mehr Parallelität und flexibler Architekturen geleitet wird. Und eine Vereinigung von EDA-Konzepten (Event Driven Architecture) könnte das Hosting und die Kommunikation von Softwarezellen vereinfachen - im Großen wie im Kleinen (innerhalb von Prozessen).
Aber davon ein andermal... Einstweilen Achtung vor der gläsernen Decke "Synchronizität"! Synchrone Verarbeitung durch scale-up zu beschleunigen, führt nicht immer so weit, wie Sie denken mögen.