Isso pode parecer uma pergunta estranha, mas no meu departamento estamos tendo problemas com a seguinte situação:
Estamos trabalhando aqui em um aplicativo de servidor, que está crescendo cada vez mais, mesmo no momento em que estamos pensando em dividi-lo em diferentes partes (arquivos DLL), carregando dinamicamente quando necessário e descarregando posteriormente, para poder lidar com os problemas de desempenho.
Mas: as funções que estamos usando estão transmitindo parâmetros de entrada e saída como objetos STL e, como mencionado em uma resposta de estouro de pilha , essa é uma péssima idéia. (A postagem contém algumas soluções e hacks, mas tudo não parece muito sólido.)
Obviamente, poderíamos substituir os parâmetros de entrada / saída por tipos C ++ padrão e criar objetos STL a partir daqueles que estavam dentro das funções, mas isso pode estar causando queda no desempenho.
Tudo bem concluir que, caso você esteja pensando em construir um aplicativo, que pode crescer tanto que um único PC não aguenta mais, você não deve usar o STL como uma tecnologia?
Mais informações sobre esta questão:
Parece haver alguns mal-entendidos sobre a questão: o problema é o seguinte:
Meu aplicativo está usando uma quantidade enorme de desempenho (CPU, memória) para concluir seu trabalho, e eu gostaria de dividir este trabalho em partes diferentes (como o programa já está dividido em várias funções), não é tão difícil criar algumas DLLs fora do meu aplicativo e colocar algumas das funções na tabela de exportação dessas DLLs. Isso resultaria na seguinte situação:
+-----------+-----------+----
| Machine1 | Machine2 | ...
| App_Inst1 | App_Inst2 | ...
| | |
| DLL1.1 | DLL2.1 | ...
| DLL1.2 | DLL2.2 | ...
| DLL1.x | DLL2.x | ...
+-----------+-----------+----
App_Inst1 é a instância do aplicativo, instalada na Máquina1, enquanto App_Inst2 é a instância do mesmo aplicativo, instalada na Máquina2.
DLL1.x é uma DLL, instalada na Máquina1, enquanto DLL2.x é uma DLL, instalada na Máquina2.
DLLx.1 abrange a função exportada1.
DLLx.2 abrange a função exportada2.
Agora na Machine1 eu gostaria de executar function1 e function2. Sei que isso sobrecarregará o Machine1, portanto, gostaria de enviar uma mensagem para App_Inst2, solicitando que a instância do aplicativo execute a função2.
Os parâmetros de entrada / saída de function1 e function2 são objetos STL (C ++ Standard Type Library), e regularmente posso esperar que o cliente faça atualizações de App_Inst1, App_Inst2, DLLx.y (mas não todos, o cliente pode atualizar o Machine1, mas não Machine2, ou apenas atualize os aplicativos, mas não as DLLs ou vice-versa, ...). Obviamente, se a interface (parâmetros de entrada / saída) mudar, o cliente será forçado a fazer atualizações completas.
No entanto, como mencionado no URL StackOverflow referido, uma simples recompilação de App_Inst1 ou de uma das DLLs pode fazer com que todo o sistema desmorone, portanto, meu título original desta postagem, desaconselha o uso de STL (C ++ Standard Template Library) para grandes aplicações.
Espero que, por este meio, tenha esclarecido algumas dúvidas / dúvidas.
Respostas:
Esse é um problema XY clássico, extremamente frio.
Seu verdadeiro problema são problemas de desempenho. No entanto, sua pergunta deixa claro que você não fez nenhum perfil ou outra avaliação de onde os problemas de desempenho realmente vêm. Em vez disso, você espera que dividir seu código em DLLs resolva magicamente o problema (o que não acontecerá, para constar) e agora você está preocupado com um aspecto dessa não solução.
Em vez disso, você precisa resolver o problema real. Se você tiver vários executáveis, verifique qual deles está causando a desaceleração. Enquanto você está nisso, verifique se o programa está demorando todo o tempo de processamento, e não um driver Ethernet mal configurado ou algo assim. E depois disso, comece a criar um perfil das várias tarefas no seu código. O temporizador de alta precisão é seu amigo aqui. A solução clássica é monitorar os tempos médios e de pior caso de processamento para obter um pedaço de código.
Quando você tiver dados, poderá descobrir como lidar com o problema e, então, onde otimizar.
fonte
Se você precisar dividir um software entre várias máquinas físicas, precisará de alguma forma de serialização ao transmitir dados entre máquinas, pois somente em alguns casos você pode realmente enviar o mesmo binário exato entre máquinas. A maioria dos métodos de serialização não tem problemas ao lidar com tipos de STL, portanto, esse caso não é algo que me preocuparia.
Se você precisar dividir um aplicativo em DLLs (Bibliotecas Compartilhadas) (antes de fazer isso por motivos de desempenho, verifique se ele realmente resolveria seus problemas de desempenho) a passagem de objetos STL pode ser um problema, mas não precisa ser. Como o link que você forneceu já descreve, a passagem de objetos STL funcionará se você usar o mesmo compilador e as mesmas configurações. Se os usuários fornecerem as DLLs, talvez você não consiga contar com facilidade. Se você fornecer todas as DLLs e compilar tudo junto, no entanto, poderá contar com isso e o uso de objetos STL através dos limites da DLL se tornará muito possível. Você ainda precisa observar as configurações do compilador para não obter vários heaps diferentes se passar a propriedade do objeto, embora esse não seja um problema específico da STL.
fonte
A RAM é barata e, portanto, o código inativo é barato. O código de carregamento e descarregamento (especialmente o descarregamento) é um processo frágil e é improvável que tenha um efeito significativo no desempenho de seus programas no hardware moderno de desktop / servidor.
O cache é mais caro, mas isso afeta apenas o código que está ativo recentemente, e não o código que está na memória sem uso.
Em geral, os programas superam seus computadores por causa do tamanho dos dados ou do tempo da CPU, não do tamanho do código. Se o tamanho do seu código está ficando tão grande que está causando grandes problemas, é provável que você queira ver por que isso está acontecendo.
Deve estar tudo bem, desde que as dlls e o executável sejam todos criados com o mesmo compilador e vinculados dinamicamente à mesma biblioteca de tempo de execução C ++. Daqui resulta que, se a aplicação e as dlls associadas forem construídas e implantadas como uma única unidade, isso não deverá ser um problema.
O problema é quando as bibliotecas são construídas por pessoas diferentes ou podem ser atualizadas separadamente.
Na verdade não.
Depois de começar a espalhar um aplicativo por várias máquinas, você tem uma série de considerações sobre como passa os dados entre essas máquinas. Os detalhes de se tipos STL ou mais básicos são usados provavelmente se perderão no ruído.
fonte
Não, não acho que essa conclusão se segue. Mesmo que seu programa seja distribuído por várias máquinas, não há razão para que o uso do STL o force internamente a usá-lo na comunicação entre módulos / processos.
Na verdade, eu argumentaria que você deve separar o design de interfaces externas da implementação interna desde o início, pois as primeiras serão mais sólidas / difíceis de mudar em comparação com as usadas internamente
fonte
Você está perdendo o objetivo dessa pergunta.
Existem basicamente dois tipos de DLL. Você e os de outra pessoa. O "problema STL" é que você e eles podem não estar usando o mesmo compilador. Obviamente, isso não é um problema para sua própria DLL.
fonte
Se você criar as DLLs da mesma árvore de origem ao mesmo tempo com as mesmas opções de compilação e compilação, funcionará OK.
No entanto, a maneira "com sabor do Windows" de dividir um aplicativo em várias partes, algumas das quais reutilizáveis, são componentes COM . Eles podem ser pequenos (controles ou codecs individuais) ou grandes (o IE está disponível como um controle COM, em mshtml.dll).
Para um aplicativo de servidor, isso provavelmente terá uma eficiência terrível ; só é realmente viável quando você tem um aplicativo que se move por várias fases por um longo período de tempo, para saber quando algo não será necessário novamente. Isso me lembra jogos do DOS usando o mecanismo de sobreposição.
Além disso, se o seu sistema de memória virtual estiver funcionando corretamente, ele cuidará disso paginando páginas de códigos não utilizadas.
Compre um PC maior.
Não esqueça que, com a otimização correta, um laptop pode superar um cluster hadoop.
Se você realmente precisa de vários sistemas, precisa pensar muito cuidadosamente sobre os limites entre eles, pois é aí que está o custo de serialização. É aqui que você deve começar a olhar para estruturas como o MPI.
fonte
A primeira parte faz sentido (dividir o aplicativo em máquinas diferentes, por razões de desempenho).
A segunda parte (carregar e descarregar bibliotecas) não faz sentido, pois esse é um esforço extra a ser feito e não melhorará (realmente) as coisas.
O problema que você está descrevendo é melhor resolvido com máquinas de computação dedicadas, mas elas não devem funcionar com o mesmo aplicativo (principal).
A solução clássica é assim:
Entre as máquinas front-end e de computação, você pode ter coisas extras, como balanceadores de carga e monitoramento de desempenho, e manter o processamento especializado em máquinas dedicadas é bom para otimizações de cache e taxa de transferência.
Isso de forma alguma implica carregamento / descarregamento extra de DLLs, nem nada a ver com o STL.
Ou seja, use o STL internamente, conforme necessário, e serialize seus dados entre os elementos (consulte buffers de protocolo e protocolo grpc e o tipo de problemas que eles resolvem).
Dito isto, com as informações limitadas que você forneceu, parece o clássico problema xy (como disse @Graham).
fonte