Das hört sich vielleicht komisch an, aber in meiner Abteilung haben wir Probleme mit der folgenden Situation:
Wir arbeiten hier an einer Serveranwendung, die immer größer wird, auch wenn wir überlegen, sie in verschiedene Teile (DLL-Dateien) aufzuteilen, bei Bedarf dynamisch zu laden und anschließend zu entladen, um damit umgehen zu können die Leistungsprobleme.
Aber: Die von uns verwendeten Funktionen übergeben Eingabe- und Ausgabeparameter als STL-Objekte, und wie in einer Stack Overflow-Antwort erwähnt , ist dies 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 denen erstellen, die sich einmal in den Funktionen befinden. Dies könnte jedoch zu Leistungseinbußen führen.
Ist es in Ordnung zu folgern, dass Sie STL überhaupt nicht als Technologie verwenden dürfen, wenn 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 scheinen einige Missverständnisse in Bezug auf die Frage zu bestehen: Es handelt sich um das folgende Problem:
Meine Anwendung verbraucht sehr viel Leistung (CPU, Speicher), um ihre Arbeit abzuschließen, und ich möchte diese Arbeit aufteilen Da das Programm bereits in mehrere Funktionen unterteilt ist, ist es nicht so schwierig, einige DLLs aus meiner Anwendung 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 auf Computer1 installierte Instanz der Anwendung, während App_Inst2 die auf Computer2 installierte Instanz derselben Anwendung ist.
DLL1.x ist eine DLL, die auf Machine1 installiert ist, während DLL2.x eine DLL ist, die auf Machine2 installiert ist.
DLLx.1 deckt die exportierte Funktion1 ab.
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 auffordern, function2 auszuführen.
Die Eingabe- / Ausgabeparameter von function1 und function2 sind STL-Objekte (C ++ Standard Type Library), und ich erwarte, dass der Kunde regelmäßig Aktualisierungen von App_Inst1, App_Inst2, DLLx.y durchführt (aber nicht alle, der Kunde aktualisiert möglicherweise Machine1, aber nicht Machine2, oder aktualisieren Sie nur die Anwendungen, 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 jedoch eine einfache Neukompilierung von App_Inst1 oder einer der DLLs dazu führen, dass das gesamte System auseinanderfällt. Daher mein ursprünglicher Titel dieses Beitrags, in dem die Verwendung von STL (C ++ Standard Template) nicht empfohlen wird Bibliothek) für große Anwendungen.
Ich hoffe, dass ich hiermit einige Fragen / Zweifel ausgeräumt habe.
Antworten:
Dies ist ein eiskaltes klassisches XY-Problem.
Ihr eigentliches Problem sind Leistungsprobleme. Ihre Frage verdeutlicht jedoch, dass Sie keine Profilerstellung oder andere Bewertungen vorgenommen haben, um festzustellen, woher die Leistungsprobleme tatsächlich stammen. Stattdessen hoffen Sie, dass das Aufteilen Ihres Codes in DLLs das Problem auf magische Weise lösen wird (was für die Aufzeichnung nicht der Fall ist), und jetzt sind Sie besorgt ü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 dabei sicher, dass Ihr Programm die gesamte Verarbeitungszeit in Anspruch nimmt und kein schlecht konfigurierter Ethernet-Treiber oder ähnliches. Beginnen Sie anschließend mit der Profilerstellung für die verschiedenen Aufgaben in Ihrem Code. Der hochpräzise Timer ist hier Ihr Freund. Die klassische Lösung besteht darin, die durchschnittlichen Verarbeitungszeiten und die Verarbeitungszeiten im ungünstigsten Fall für einen Teil des Codes zu überwachen.
Wenn Sie Daten haben, können Sie herausfinden, wie Sie mit dem Problem umgehen können, und dann können Sie herausfinden, wo Sie optimieren müssen.
quelle
Wenn Sie eine Software auf mehrere physische Maschinen aufteilen müssen, müssen Sie beim Übertragen von Daten zwischen Maschinen eine gewisse Form der Serialisierung verwenden, da Sie in einigen Fällen nur genau die gleiche Binärdatei zwischen Maschinen senden können. Die meisten Serialisierungsmethoden haben keine Probleme bei der Verarbeitung von STL-Typen, sodass mir dieser Fall keine Sorgen machen 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 es Ihre Leistungsprobleme tatsächlich lösen würde), kann die Übergabe von STL-Objekten ein Problem sein, muss es aber nicht. Wie der von Ihnen angegebene Link bereits beschreibt, funktioniert das Übergeben von AWL-Objekten, wenn Sie denselben Compiler und dieselben Compilereinstellungen verwenden. Wenn Benutzer die DLLs bereitstellen, können Sie sich möglicherweise nicht ohne Weiteres darauf verlassen. Wenn Sie jedoch alle DLLs bereitstellen und alles zusammen kompilieren, können Sie sich möglicherweise darauf verlassen und STL-Objekte über DLL-Grenzen hinweg verwenden. 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.
quelle
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 Ihres Programms auf moderner Desktop- / Server-Hardware.
Cache ist teurer, wirkt sich jedoch nur auf Code aus, der kürzlich aktiv war, und nicht auf Code, der nicht im Arbeitsspeicher verwendet wurde.
Im Allgemeinen wachsen Programme aufgrund der Datengröße oder der CPU-Zeit aus ihren Computern heraus, nicht aufgrund der Codegröße. Wenn Ihre Code-Größe so groß wird, dass es zu großen Problemen kommt, möchten Sie wahrscheinlich wissen, warum dies überhaupt geschieht.
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 einzelne Einheit erstellt und bereitgestellt werden.
Problematisch wird es, wenn die Bibliotheken von verschiedenen Personen erstellt oder separat aktualisiert werden können.
Nicht wirklich.
Sobald Sie damit beginnen, eine Anwendung auf mehrere Computer zu 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.
quelle
Nein, ich denke nicht, dass diese Schlussfolgerung folgt. Auch wenn Ihr Programm auf mehrere Maschinen verteilt ist, besteht kein Grund, dass Sie durch die interne Verwendung der STL gezwungen sind, sie für die Kommunikation zwischen Modulen und Prozessen zu verwenden.
Tatsächlich 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 sein werden als das, was intern verwendet wird
quelle
Sie verpassen den Punkt dieser Frage.
Grundsätzlich gibt es zwei Arten von DLLs. Deine eigene und die von jemand anderem. 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.
quelle
Wenn Sie die DLLs gleichzeitig mit demselben Compiler und denselben Erstellungsoptionen aus demselben Quellbaum erstellen, funktioniert dies in Ordnung.
Die "Windows-gewürzte" Art, eine Anwendung in mehrere Teile aufzuteilen, von denen einige wiederverwendbar sind, sind jedoch COM-Komponenten . Dies können kleine (einzelne Steuerelemente oder Codecs) oder große (IE ist als COM-Steuerelement in mshtml.dll verfügbar) sein.
Für eine Serveranwendung wird dies wahrscheinlich eine schreckliche Effizienz haben. Dies ist nur dann wirklich sinnvoll, wenn Sie eine Anwendung haben, die über einen langen Zeitraum mehrere Phasen durchläuft, sodass 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, übernimmt es dies für Sie, indem es nicht verwendete Codepages auslagert.
Kaufen Sie einen größeren PC.
Vergessen Sie nicht, dass ein Laptop mit der richtigen Optimierung einen Hadoop-Cluster übertreffen kann.
Wenn Sie wirklich mehrere Systeme benötigen, müssen Sie sich die Grenzen zwischen ihnen genau überlegen, da dort die Serialisierungskosten anfallen. Hier sollten Sie sich mit Frameworks wie MPI befassen.
quelle
Der erste Teil ist sinnvoll (Aufteilung der Anwendung auf verschiedene Maschinen aus Leistungsgründen).
Der zweite Teil (Laden und Entladen von Bibliotheken) macht keinen Sinn, da dies zusätzlichen Aufwand bedeutet 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:
Zwischen dem Front-End und den Rechenmaschinen stehen möglicherweise zusätzliche Funktionen wie Lastausgleich und Leistungsüberwachung zur Verfügung, und die spezielle Verarbeitung auf dedizierten Maschinen ist gut für die Caching- und Durchsatzoptimierung geeignet.
Dies impliziert 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 von ihnen gelösten Probleme).
Dies sagte, mit den begrenzten Informationen, die Sie zur Verfügung gestellt haben, sieht dies wie das klassische xy-Problem aus (wie @Graham sagte).
quelle