Cela peut sembler une question étrange, mais dans mon département, nous avons des problèmes avec la situation suivante:
Nous travaillons ici sur une application serveur, qui s'agrandit de plus en plus, même au moment où nous envisageons de la diviser en différentes parties (fichiers DLL), en chargeant dynamiquement en cas de besoin et en déchargeant par la suite, afin de pouvoir gérer les problèmes de performance.
Mais: les fonctions que nous utilisons passent des paramètres d'entrée et de sortie en tant qu'objets STL, et comme mentionné dans une réponse Stack Overflow , c'est une très mauvaise idée. (Le message contient quelques ± solutions et hacks, mais tout ne semble pas très solide.)
Évidemment, nous pourrions remplacer les paramètres d'entrée / sortie par des types C ++ standard et créer des objets STL à partir de ceux une fois à l'intérieur des fonctions, mais cela pourrait entraîner des baisses de performances.
Est-il correct de conclure que, si vous envisagez de créer une application, qui pourrait devenir si grande qu'un seul PC ne peut plus la gérer, vous ne devez pas du tout utiliser STL comme technologie?
Plus d'informations sur cette question:
il semble y avoir des malentendus sur la question: le problème est le suivant:
mon application utilise une énorme quantité de performances (CPU, mémoire) afin de terminer son travail, et je voudrais diviser ce travail en différentes parties (comme le programme est déjà divisé en plusieurs fonctions), il n'est pas si difficile de créer des DLL à partir de mon application et de mettre certaines des fonctions dans la table d'exportation de ces DLL. Cela entraînerait la situation suivante:
+-----------+-----------+----
| Machine1 | Machine2 | ...
| App_Inst1 | App_Inst2 | ...
| | |
| DLL1.1 | DLL2.1 | ...
| DLL1.2 | DLL2.2 | ...
| DLL1.x | DLL2.x | ...
+-----------+-----------+----
App_Inst1 est l'instance de l'application, installée sur Machine1, tandis que App_Inst2 est l'instance de la même application, installée sur Machine2.
DLL1.x est une DLL, installée sur Machine1, tandis que DLL2.x est une DLL, installée sur Machine2.
DLLx.1 couvre la fonction exportée 1.
DLLx.2 couvre la fonction exportée2.
Maintenant, sur Machine1, j'aimerais exécuter function1 et function2. Je sais que cela surchargera Machine1, donc je voudrais envoyer un message à App_Inst2, demandant à cette instance d'application d'exécuter function2.
Les paramètres d'entrée / sortie de function1 et function2 sont des objets STL (C ++ Standard Type Library), et régulièrement je pourrais m'attendre à ce que le client fasse des mises à jour d'App_Inst1, App_Inst2, DLLx.y (mais pas tous, le client peut mettre à niveau Machine1 mais pas Machine2, ou seulement mettre à niveau les applications mais pas les DLL ou vice versa, ...). Évidemment, si l'interface (paramètres d'entrée / sortie) change, le client est obligé de procéder à des mises à niveau complètes.
Cependant, comme mentionné dans l'URL StackOverflow référencée, une simple recompilation d'App_Inst1 ou de l'une des DLL peut entraîner l'effondrement de l'ensemble du système, d'où mon titre d'origine de cet article, déconseillant l'utilisation de STL (C ++ Standard Template Library) pour les grandes applications.
J'espère que par la présente, j'ai dissipé certaines questions / doutes.
Réponses:
Il s'agit d'un problème XY classique et froid.
Votre vrai problème, ce sont les problèmes de performances. Cependant, votre question indique clairement que vous n'avez effectué aucun profilage ni aucune autre évaluation de l'origine des problèmes de performances. Au lieu de cela, vous espérez que le fractionnement de votre code en DLL résoudra comme par magie le problème (ce qu'il ne fera pas, pour mémoire), et maintenant vous vous inquiétez d'un aspect de cette non-solution.
Au lieu de cela, vous devez résoudre le vrai problème. Si vous avez plusieurs exécutables, vérifiez lequel est à l'origine du ralentissement. Pendant que vous y êtes, assurez-vous que c'est votre programme qui prend tout le temps de traitement, et non un pilote Ethernet mal configuré ou quelque chose comme ça. Et après cela, commencez à profiler les différentes tâches de votre code. La minuterie de haute précision est votre amie ici. La solution classique consiste à surveiller les temps de traitement moyens et les pires cas pour un morceau de code.
Lorsque vous avez des données, vous pouvez déterminer comment résoudre le problème, puis déterminer où optimiser.
la source
Si vous devez diviser un logiciel entre plusieurs machines physiques, vous devez avoir une certaine forme de sérialisation lors du transfert de données entre machines car seulement dans certains cas, vous pouvez simplement envoyer le même binaire exact entre machines. La plupart des méthodes de sérialisation n'ont aucun problème à gérer les types STL, donc ce cas ne m'inquiète pas.
Si vous devez diviser une application en bibliothèques partagées (DLL) (avant de le faire pour des raisons de performances, vous devez vraiment vous assurer que cela résoudrait réellement vos problèmes de performances) la transmission d'objets STL peut être un problème mais ne doit pas l'être. Comme le lien que vous avez fourni décrit déjà, le passage d'objets STL fonctionne si vous utilisez le même compilateur et les mêmes paramètres de compilateur. Si les utilisateurs fournissent les DLL, vous ne pourrez peut-être pas facilement compter sur cela. Cependant, si vous fournissez toutes les DLL et compilez tout ensemble, vous pourrez peut-être compter dessus et utiliser des objets STL au-delà des limites des DLL devient tout à fait possible. Vous devez toujours faire attention à vos paramètres de compilation afin de ne pas obtenir plusieurs tas différents si vous passez la propriété de l'objet, bien que ce ne soit pas un problème spécifique à la STL.
la source
La RAM est bon marché et donc le code inactif est bon marché. Le chargement et le déchargement de code (en particulier le déchargement) est un processus fragile et il est peu probable qu'il ait un effet significatif sur les performances de vos programmes sur du matériel de bureau / serveur moderne.
Le cache est plus cher, mais cela n'affecte que le code récemment actif, pas le code qui est en mémoire inutilisé.
En général, les programmes dépassent leurs ordinateurs en raison de la taille des données ou du temps processeur, et non de la taille du code. Si la taille de votre code devient si grande qu'elle cause des problèmes majeurs, vous voudrez probablement chercher pourquoi cela se produit en premier lieu.
Cela devrait être correct tant que les DLL et l'exécutable sont tous construits avec le même compilateur et liés dynamiquement à la même bibliothèque d'exécution C ++. Il s'ensuit que si l'application et ses DLL associées sont construites et déployées comme une seule unité, cela ne devrait pas poser de problème.
Là où cela peut devenir un problème, c'est lorsque les bibliothèques sont construites par différentes personnes ou peuvent être mises à jour séparément.
Pas vraiment.
Une fois que vous avez commencé à répartir une application sur plusieurs machines, vous avez toute une série de considérations sur la façon dont vous transmettez les données entre ces machines. Les détails sur l'utilisation de types STL ou de types plus basiques risquent d'être perdus dans le bruit.
la source
Non, je ne pense pas que cette conclusion s'ensuit. Même si votre programme est distribué sur plusieurs machines, il n'y a aucune raison que l'utilisation de la STL en interne vous oblige à l'utiliser dans la communication inter-modules / processus.
En fait, je dirais que vous devriez séparer la conception des interfaces externes de l'implémentation interne dès le départ, car les premières seront plus solides / difficiles à changer par rapport à ce qui est utilisé en interne
la source
Vous manquez le point de cette question.
Il existe essentiellement deux types de DLL. Le vôtre et celui de quelqu'un d'autre. Le «problème STL» est que vous et eux n'utilisez peut-être pas le même compilateur. Évidemment, ce n'est pas un problème pour votre propre DLL.
la source
Si vous créez les DLL à partir de la même arborescence source en même temps avec le même compilateur et les mêmes options de génération, cela fonctionnera correctement.
Cependant, la façon "Windows" de diviser une application en plusieurs parties dont certaines sont réutilisables est les composants COM . Ceux-ci peuvent être petits (contrôles individuels ou codecs) ou grands (IE est disponible en tant que contrôle COM, dans mshtml.dll).
Pour une application serveur, cela va probablement avoir une efficacité terrible ; ce n'est vraiment viable que si vous avez une application qui passe par plusieurs phases sur une longue période de temps afin que vous sachiez quand quelque chose ne sera plus nécessaire. Cela me rappelle les jeux DOS utilisant le mécanisme de superposition.
En outre, si votre système de mémoire virtuelle fonctionne correctement, il s'en occupera en paginant les pages de codes inutilisées.
Achetez un PC plus grand.
N'oubliez pas qu'avec la bonne optimisation, un ordinateur portable peut surpasser un cluster hadoop.
Si vous avez vraiment besoin de plusieurs systèmes, vous devez réfléchir très attentivement à la frontière entre eux, car c'est là que se situe le coût de sérialisation. C'est là que vous devriez commencer à regarder des frameworks comme MPI.
la source
La première partie est logique (fractionnement de l'application sur différentes machines, pour des raisons de performances).
La deuxième partie (chargement et déchargement des bibliothèques) n'a pas de sens, car c'est un effort supplémentaire à faire, et cela n'améliorera pas (vraiment) les choses.
Le problème que vous décrivez est mieux résolu avec des machines de calcul dédiées, mais celles-ci ne devraient pas fonctionner avec la même application (principale).
La solution classique ressemble à ceci:
Entre les machines frontales et de calcul, vous pouvez avoir des choses supplémentaires, telles que des équilibreurs de charge et une surveillance des performances, et le traitement spécialisé sur des machines dédiées est bon pour la mise en cache et les optimisations de débit.
Cela n'implique en aucun cas un chargement / déchargement supplémentaire des DLL, ni rien à voir avec la STL.
Autrement dit, utilisez STL en interne selon les besoins et sérialisez vos données entre les éléments (voir grpc et tampons de protocole et le type de problèmes qu'ils résolvent).
Cela dit, avec les informations limitées que vous avez fournies, cela ressemble au problème xy classique (comme l'a dit @Graham).
la source