it-swarm.com.de

Sollte die STL bei großen Anwendungen vermieden werden?

Das mag sich nach einer seltsamen Frage anhören, aber in meiner Abteilung haben wir Probleme mit der folgenden Situation:

Wir arbeiten hier an einer Serveranwendung, die immer größer wird, selbst wenn wir überlegen, sie in verschiedene Teile (DLL-Dateien) aufzuteilen, bei Bedarf dynamisch zu laden und anschließend zu entladen, um sie verarbeiten zu können die Leistungsprobleme.

Aber: Die Funktionen, die wir verwenden, übergeben Eingabe- und Ausgabeparameter als STL-Objekte, und wie in einer Antwort zum Stapelüberlauf erwähnt , dies ist eine sehr schlechte Idee. (Der Beitrag enthält einige ± Lösungen und Hacks, aber alles sieht nicht sehr solide aus.)

Natürlich könnten wir die Eingabe-/Ausgabeparameter durch Standard-C++ - Typen ersetzen und STL-Objekte aus diesen innerhalb der Funktionen erstellen, aber dies könnte zu Leistungseinbußen führen.

Ist es in Ordnung zu schließen, dass Sie STL überhaupt nicht als Technologie verwenden dürfen, falls Sie überlegen, eine Anwendung zu erstellen, die möglicherweise so groß wird, dass ein einzelner PC nicht mehr damit umgehen kann?

Weitere Hintergrundinformationen zu dieser Frage:
Es scheint einige Missverständnisse in Bezug auf die Frage zu geben: Das Problem ist das Folgende:
Meine Anwendung verwendet eine enorme Menge an Leistung (CPU, Speicher), um ihre Arbeit abzuschließen, und ich möchte diese Arbeit in verschiedene Teile aufteilen (da das Programm bereits in mehrere Funktionen aufgeteilt ist), ist dies nicht der Fall Es ist schwierig, einige DLLs aus meiner Anwendung heraus zu erstellen und einige der Funktionen in die Exporttabelle dieser DLLs aufzunehmen. Dies würde zu folgender Situation führen:

+-----------+-----------+----
| Machine1  | Machine2  | ...
| App_Inst1 | App_Inst2 | ...
|           |           |    
| DLL1.1    | DLL2.1    | ...
| DLL1.2    | DLL2.2    | ...
| DLL1.x    | DLL2.x    | ...
+-----------+-----------+----

App_Inst1 ist die Instanz der Anwendung, die auf Maschine1 installiert ist, während App_Inst2 die Instanz derselben Anwendung ist, die auf Maschine2 installiert ist.
DLL1.x ist eine auf Maschine1 installierte DLL, während DLL2.x eine auf Maschine2 installierte DLL ist.
DLLx.1 behandelt die exportierte Funktion1.
DLLx.2 deckt die exportierte Funktion2 ab.

Jetzt möchte ich auf Maschine1 Funktion1 und Funktion2 ausführen. Ich weiß, dass dies Machine1 überlasten wird, daher möchte ich eine Nachricht an App_Inst2 senden und diese Anwendungsinstanz bitten, Funktion2 auszuführen.

Die Eingabe-/Ausgabeparameter von Funktion1 und Funktion2 sind STL-Objekte (C++ Standard Type Library), und ich kann regelmäßig erwarten, dass der Kunde Aktualisierungen von App_Inst1, App_Inst2, DLLx.y vornimmt (aber nicht alle, der Kunde kann jedoch Maschine1 aktualisieren, aber nicht Machine2 oder nur die Anwendungen aktualisieren, aber nicht die DLLs oder umgekehrt, ...). Wenn sich die Schnittstelle (Eingabe-/Ausgabeparameter) ändert, ist der Kunde offensichtlich gezwungen, vollständige Upgrades durchzuführen.

Wie in der angegebenen StackOverflow-URL erwähnt, kann eine einfache Neukompilierung von App_Inst1 oder einer der DLLs dazu führen, dass das gesamte System auseinanderfällt. Daher rät mein ursprünglicher Titel dieses Beitrags von der Verwendung von STL (C++ Standard Template) ab Bibliothek) für große Anwendungen.

Ich hoffe, dass ich hiermit einige Fragen/Zweifel ausgeräumt habe.

25
Dominique

Dies ist ein eiskaltes klassisches X-Y-Problem.

Ihr echtes Problem sind Leistungsprobleme. Ihre Frage macht jedoch deutlich, dass Sie keine Profilerstellung oder andere Bewertungen vorgenommen haben, woher die Leistungsprobleme tatsächlich stammen. Stattdessen hoffen Sie, dass das Aufteilen Ihres Codes in DLLs das Problem auf magische Weise löst (was für den Datensatz nicht der Fall ist), und jetzt machen Sie sich Sorgen über einen Aspekt dieser Nichtlösung.

Stattdessen müssen Sie das eigentliche Problem lösen. Wenn Sie mehrere ausführbare Dateien haben, überprüfen Sie, welche die Verlangsamung verursacht. Stellen Sie sicher, dass Ihr Programm die gesamte Verarbeitungszeit in Anspruch nimmt und nicht ein schlecht konfigurierter Ethernet-Treiber oder ähnliches. Beginnen Sie danach mit der Profilerstellung der verschiedenen Aufgaben in Ihrem Code. Der hochpräzise Timer ist hier dein Freund. Die klassische Lösung besteht darin, die durchschnittlichen und Worst-Case-Verarbeitungszeiten für einen Codeabschnitt zu überwachen.

Wenn Sie Daten haben, können Sie herausfinden, wie Sie mit dem Problem umgehen können, und dann herausfinden, wo Sie optimieren müssen.

111
Graham

Wenn Sie eine Software auf mehrere physische Maschinen aufteilen müssen, müssen Sie beim Übertragen von Daten zwischen Maschinen eine Form der Serialisierung durchführen, da Sie nur in einigen Fällen tatsächlich genau dieselbe Binärdatei zwischen Maschinen senden können. Die meisten Serialisierungsmethoden haben keine Probleme beim Umgang mit STL-Typen, sodass mich dieser Fall nicht beunruhigen würde.

Wenn Sie eine Anwendung in Shared Libraries (DLLs) aufteilen müssen (bevor Sie dies aus Leistungsgründen tun, sollten Sie wirklich sicherstellen, dass Ihre Leistungsprobleme tatsächlich gelöst werden), kann das Übergeben von STL-Objekten ein Problem sein, muss es aber nicht sein. Wie der von Ihnen bereitgestellte Link bereits beschreibt, funktioniert das Übergeben von STL-Objekten, wenn Sie denselben Compiler und dieselben Compilereinstellungen verwenden. Wenn Benutzer die DLLs bereitstellen, können Sie möglicherweise nicht einfach darauf zählen. Wenn Sie jedoch alle DLLs bereitstellen und alles zusammen kompilieren, können Sie sich möglicherweise darauf verlassen und die Verwendung von STL-Objekten über DLL Grenzen hinweg wird sehr gut möglich. Sie müssen immer noch auf Ihre Compilereinstellungen achten, damit Sie nicht mehrere verschiedene Heaps erhalten, wenn Sie den Objektbesitz übergeben, obwohl dies kein STL-spezifisches Problem ist.

38

Wir arbeiten hier an einer Serveranwendung, die immer größer wird, selbst an dem Punkt, an dem wir erwägen, sie in verschiedene Teile (DLLs) aufzuteilen, bei Bedarf dynamisch zu laden und anschließend zu entladen, um das Problem lösen zu können Performance-Probleme

RAM ist billig und daher ist inaktiver Code billig. Das Laden und Entladen von Code (insbesondere das Entladen) ist ein fragiler Prozess und hat wahrscheinlich keine wesentlichen Auswirkungen auf die Leistung Ihrer Programme auf moderner Desktop-/Serverhardware.

Der Cache ist teurer, wirkt sich jedoch nur auf Code aus, der kürzlich aktiv war, nicht auf Code, der nicht verwendet im Speicher gespeichert ist.

Im Allgemeinen wachsen Programme aufgrund der Datengröße oder der CPU-Zeit aus ihren Computern heraus, nicht aufgrund der Codegröße. Wenn Ihre Codegröße so groß wird, dass sie große Probleme verursacht, möchten Sie wahrscheinlich untersuchen, warum dies überhaupt geschieht.

Aber: Die Funktionen, die wir verwenden, übergeben Eingabe- und Ausgabeparameter als STL-Objekte, und wie in dieser StackOverflow-URL erwähnt, ist dies eine sehr schlechte Idee.

Es sollte in Ordnung sein, solange die DLLs und die ausführbare Datei alle mit demselben Compiler erstellt und dynamisch mit derselben C++ - Laufzeitbibliothek verknüpft sind. Daraus folgt, dass es kein Problem sein sollte, wenn die Anwendung und die zugehörigen DLLs als eine Einheit erstellt und bereitgestellt werden.

Es kann zu einem Problem werden, wenn die Bibliotheken von verschiedenen Personen erstellt oder separat aktualisiert werden können.

Ist es in Ordnung zu schließen, dass Sie STL überhaupt nicht als Technologie verwenden dürfen, falls Sie überlegen, eine Anwendung zu erstellen, die möglicherweise so groß wird, dass ein einzelner PC nicht mehr damit umgehen kann?

Nicht wirklich.

Sobald Sie eine Anwendung auf mehrere Computer verteilen, müssen Sie eine ganze Reihe von Überlegungen anstellen, wie Sie die Daten zwischen diesen Computern übertragen. Die Details, ob STL-Typen oder einfachere Typen verwendet werden, gehen wahrscheinlich im Rauschen verloren.

20
Peter Green

Nein, ich glaube nicht, dass diese Schlussfolgerung folgt. Selbst wenn Ihr Programm auf mehrere Computer verteilt ist, gibt es keinen Grund, warum die interne Verwendung der STL Sie dazu zwingt, es in der Kommunikation zwischen Modulen und Prozessen zu verwenden.

In der Tat würde ich argumentieren, dass Sie das Design externer Schnittstellen von Anfang an von der internen Implementierung trennen sollten, da erstere solider/schwerer zu ändern sind als die intern verwendeten

13
Bwmat

Sie verpassen den Punkt dieser Frage.

Grundsätzlich gibt es zwei Arten von DLLs. Dein eigenes und das eines anderen. Das "STL-Problem" besteht darin, dass Sie und sie möglicherweise nicht denselben Compiler verwenden. Dies ist natürlich kein Problem für Ihre eigene DLL.

7
MSalters

Wenn Sie die DLLs zur gleichen Zeit mit demselben Compiler und denselben Build-Optionen aus demselben Quellbaum erstellen, funktioniert dies einwandfrei.

Die "Windows-Variante" zum Aufteilen einer Anwendung in mehrere Teile, von denen einige wiederverwendbar sind, sind jedoch COM-Komponenten . Diese können klein (einzelne Steuerelemente oder Codecs) oder groß (IE ist als COM-Steuerelement in mshtml.dll verfügbar) sein.

bei Bedarf dynamisch laden und anschließend entladen

Für eine Serveranwendung wird dies wahrscheinlich eine schreckliche Effizienz haben; Dies ist nur dann wirklich sinnvoll, wenn Sie eine Anwendung haben, die sich über einen langen Zeitraum durch mehrere Phasen bewegt, damit Sie wissen, wann etwas nicht mehr benötigt wird. Es erinnert mich an DOS-Spiele mit dem Overlay-Mechanismus.

Wenn Ihr virtuelles Speichersystem ordnungsgemäß funktioniert, erledigt es dies für Sie, indem nicht verwendete Codeseiten ausgelagert werden.

könnte so groß werden, dass ein einzelner PC nicht mehr damit umgehen kann

Kaufen Sie einen größeren PC.

Vergessen Sie nicht, dass mit der richtigen Optimierung kann ein Laptop einen Hadoop-Cluster übertreffen.

Wenn Sie wirklich mehrere Systeme benötigen, müssen Sie sehr genau über die Grenze zwischen ihnen nachdenken, da dort die Serialisierungskosten liegen. Hier sollten Sie sich mit Frameworks wie MPI befassen.

5
pjc50

Wir arbeiten hier an einer Serveranwendung, die immer größer wird, selbst wenn wir überlegen, sie in verschiedene Teile (DLL-Dateien) aufzuteilen, bei Bedarf dynamisch zu laden und anschließend zu entladen, um sie verarbeiten zu können die Leistungsprobleme.

Der erste Teil ist sinnvoll (Aufteilung der Anwendung auf verschiedene Maschinen aus Leistungsgründen).

Der zweite Teil (Laden und Entladen von Bibliotheken) ist nicht sinnvoll, da dies zusätzliche Anstrengungen erfordert und die Dinge nicht (wirklich) verbessert.

Das von Ihnen beschriebene Problem lässt sich besser mit dedizierten Rechenmaschinen lösen, diese sollten jedoch nicht mit derselben (Haupt-) Anwendung funktionieren.

Die klassische Lösung sieht folgendermaßen aus:

[user] [front-end] [machine1] [common resources]
                   [machine2]
                   [machine3]

Zwischen dem Front-End und den Rechenmaschinen stehen möglicherweise zusätzliche Funktionen zur Verfügung, z. B. Load Balancer und Leistungsüberwachung. Die spezielle Verarbeitung auf dedizierten Maschinen ist für das Caching und die Durchsatzoptimierung hilfreich.

Dies bedeutet in keiner Weise ein zusätzliches Laden/Entladen von DLLs oder irgendetwas, das mit der STL zu tun hat.

Das heißt, verwenden Sie STL nach Bedarf intern und serialisieren Sie Ihre Daten zwischen den Elementen (siehe grpc- und Protokollpuffer und die Art der Probleme, die sie lösen).

Angesichts der begrenzten Informationen, die Sie bereitgestellt haben, sieht dies jedoch wie das klassische x-y-Problem aus (wie @Graham sagte).

0
utnapistim