Neste post, vamos cobrir dicas e truques sobre como você pode otimizar seus projetos C ++ Builder para compilar o mais rápido possível. Enquanto definitivamente vamos gastar algum tempo olhando para otimizações voltadas para uso com TwineCompile, alguns desses truques se aplicam ao C ++ Builder em geral.
C ++ Builder e TwineCompile incluem muitas funcionalidades projetadas para otimizar a velocidade de compilação, mas muitas vezes precisam ser ajustados porque cada projeto é único e tem diferentes condições e configurações. Veremos várias dicas e quando e como aplicá-las a diferentes tipos e estruturas de projeto.
Table of Contents
Truque # 1 – TwineCompile
O primeiro truque é fácil – comece a usar TwineCompile! TwineCompile é um plugin IDE que se integra ao C ++ Builder e adiciona multi-threading, caching e outras melhorias poderosas aos compiladores C ++ Builder (Classic e CLANG). Em alguns casos, a simples instalação do TwineCompile fará com que os projetos sejam compilados 50 vezes mais rápido em estações de trabalho de compilação de última geração.
TwineCompile está disponível gratuitamente para todos os usuários do C ++ Builder 10.4.1+ com uma Assinatura de Atualização ativa por meio do Gerenciador de Pacotes GetIt. Esta deve ser a primeira parada na busca por tempos de compilação mais rápidos, pois você pode aproveitar essas melhorias de desempenho sem precisar fazer uma única alteração na estrutura ou nos arquivos do projeto (ao contrário das dicas a seguir).
Para obter TwineCompile, abra o Gerenciador de Pacotes GetIt no IDE e pesquise TwineCompile. Siga as instruções para instalá-lo.
A integração do IDE do TwineCompile conectará automaticamente os comandos IDE Compile / Make / Build para invocar o TwineCompile em vez do processo de construção do IDE. Isso permite que você continue a usar o IDE como faz hoje e aproveite ao máximo o desempenho de compilação oferecido pelo TwineCompile.
Truque # 2 do TwineCompile – CLANG Powered PCH (cabeçalhos pré-compilados)
C ++ Builder há muito tem uma arma secreta que pode fazer mágica em tempos de compilação lentos. Freqüentemente, o único aprimoramento mais eficaz é configurar e usar cabeçalhos pré-compilados em um projeto. A introdução do compilador CLANG melhorou significativamente essa funcionalidade e tornou-a muito mais fácil de usar. Se o seu projeto está usando atualmente o compilador CLANG, eu recomendo aproveitar as vantagens do suporte PCH no CLANG, pois isso fará uma enorme diferença nos seus tempos de compilação. Se o seu projeto ainda estiver usando o compilador Classic, eu recomendaria atualizá-lo para usar o compilador CLANG – você não apenas obterá a capacidade de usar um compilador C ++ moderno e compatível com os padrões com suporte C ++ v17, mas você também pode usar o sistema CLANG PCH.
O conceito por trás dos cabeçalhos pré-compilados é bastante simples – pegue um conjunto de cabeçalhos que são usados na maioria (senão em todas) das unidades de um projeto e compile-os em uma representação binária. Quando uma unidade do projeto inclui esses cabeçalhos pré-compilados, o compilador não precisa reprocessar / compilar os cabeçalhos do zero, mas pode simplesmente carregar a representação pré-compilada do disco e prosseguir para compilar o código na unidade .
É necessária alguma disciplina, pois a ordem do cabeçalho em cada unidade deve ser idêntica para garantir que o compilador possa usar o cabeçalho pré-compilado. Além disso, o cabeçalho pré-compilado não deve conter cabeçalhos que são frequentemente modificados, pois a sobrecarga de compilar os cabeçalhos é bastante significativa e você perderá todas as vantagens do cabeçalho pré-compilado se ele tiver que ser reconstruído o tempo todo.
- Comece analisando seu projeto e identificando os cabeçalhos que a maioria das unidades inclui. Isso pode exigir alguma reorganização para fazer com que a maioria ou todas as unidades incluam o mesmo conjunto de cabeçalhos. Observe que incluindo adicionais, não utilizados,
cabeçalhos não tem um efeito negativo, então se algumas unidades não usarem todos os cabeçalhos, está tudo bem. Quanto mais cabeçalhos forem pré-compilados, mais eficaz será em melhorar seus tempos de compilação.
- Se o seu projeto já tiver um arquivo de cabeçalho PCH (como o arquivo PCH .h gerado automaticamente pelo IDE para novos projetos), pule para a etapa # 6.
- Se o seu projeto não tiver um arquivo de cabeçalho PCH (como o arquivo PCH .h gerado automaticamente pelo IDE para novos projetos), adicione um novo arquivo de cabeçalho ao projeto:
- Salve o novo arquivo de cabeçalho com um nome descritivo, como ProjectNamePCH.h
- Clique com o botão direito no arquivo de cabeçalho no painel Projetos e selecione a opção Usar para pré-compilação:
- Abra este arquivo de cabeçalho pré-compilado e coloque todas as instruções de inclusão que você coletou na etapa # 1. Por exemplo:
#include <vcl.h>
#include <tchar.h>
- Percorra todas as unidades em seu projeto e remova as instruções #include que se referem aos cabeçalhos localizados no cabeçalho PCH. No topo de cada unidade, antes de qualquer outra instrução, coloque a seguinte instrução pragma para dizer ao compilador que a unidade não está ajustando o cabeçalho pré-compilado:
#pragma hdrstop
- Abra as Opções do projeto, vá para a seção Cabeçalhos pré-compilados em Compilador C ++ e selecione Gerar e usar para a opção de uso PCH
- Construa o projeto. Levará algum tempo compilando o arquivo de cabeçalho PCH na representação binária e, em seguida, as unidades subsequentes serão compiladas muito mais rápido, pois esses cabeçalhos não precisarão mais ser processados para cada unidade repetidamente.
Truque # 3 – TwineCompile PCH de cabeçalho único para o compilador Classic
Se o seu projeto ainda estiver usando o compilador Classic e você não conseguir migrá-lo para o compilador CLANG mais recente, ainda é possível obter ganhos de velocidade de compilação significativos usando cabeçalhos pré-compilados devido ao compilador clássico ter um sistema PCH incrivelmente poderoso. TwineCompile foi construído para tirar o máximo proveito deste sistema e organiza o processo de construção de forma que o compilador clássico seja chamado automaticamente com os parâmetros corretos para cada arquivo que está usando o cabeçalho pré-compilado.
Ao contrário do compilador CLANG, o compilador clássico é projetado para gerar e usar o cabeçalho pré-compilado como parte da compilação dos arquivos de origem regulares. Não há etapa de compilação separada necessária para compilar um arquivo que foi designado como o arquivo de cabeçalho pré-compilado.
Existem duas maneiras de configurar um projeto para usar um PCH de cabeçalho único com o compilador clássico:
- Usando um comando de injeção para incluir automaticamente o arquivo PCH de cabeçalho único em cada unidade como parte do processo de compilação.
- Adicionando manualmente a instrução #include para o arquivo PCH de cabeçalho único na parte superior de cada unidade.
A primeira abordagem é obviamente a mais fácil, pois garante que o cabeçalho esteja disponível em todas as unidades automaticamente. A segunda abordagem pode ser útil, pois o cabeçalho está realmente incluído em cada unidade, portanto, está disponível para navegação e outros usos, como ferramenta de análise de código.
- Assim como nas etapas do CLANG, comece analisando seu projeto e identificando os cabeçalhos que a maioria das unidades inclui.
Isso pode exigir alguma reorganização para fazer com que a maioria ou todas as unidades incluam o mesmo conjunto de cabeçalhos. Observe que incluir cabeçalhos adicionais, não usados, não tem um efeito negativo, portanto, se algumas unidades não usarem todos os cabeçalhos, tudo bem. Quanto mais cabeçalhos forem pré-compilados, mais eficaz será em melhorar seus tempos de compilação.
- Crie um novo arquivo de cabeçalho em seu projeto:
- Salve o novo arquivo de cabeçalho com um nome descritivo, como ProjectNamePCH.h
- Abra este arquivo de cabeçalho pré-compilado e coloque todas as instruções de inclusão que você coletou na etapa # 1. Por exemplo:
#include <vcl.h>
#include <tchar.h>
5a. Abordagem A – se você quiser usar a funcionalidade de injeção, abra as opções do projeto, vá para a seção de cabeçalhos pré-compilados no compilador C ++ e insira o nome do arquivo de cabeçalho na opção de cabeçalho de injeção:
5b. Abordagem B – se você quiser adicionar manualmente o cabeçalho em suas unidades, coloque a instrução #include para este arquivo de cabeçalho seguida por uma linha #pragma hdrstop no topo de qualquer unidade. Por exemplo:
#include "ProjectNamePCH.h"
#pragma hdrstop
- Abra as Opções do projeto, vá para a seção Cabeçalhos pré-compilados em Compilador C ++:
6a. Selecione a opção Gerar e usar para uso de PCH. Isso instrui TwineCompile a usar o primeiro arquivo de código-fonte para gerar o arquivo PCH e usá-lo para todas as unidades subsequentes.
6b. Selecione a opção Cache pré-compilados de cabeçalhos
6c. Insira um nome para o arquivo PCH gerado na opção Nome do arquivo PCH. Por exemplo: Project.csm. Este arquivo conterá os dados binários compilados do cabeçalho selecionado como o cabeçalho pré-compilado.
As opções devem ser semelhantes a estas:
- Abra as opções do TwineCompile no menu TwineCompile, vá para Pre-Compiled Headers e selecione a opção “Usar arquivo PCH para cada thread”. Clique OK.
- Construa o projeto. TwineCompile ajustará automaticamente as opções do compilador para cada arquivo para que possam gerar e usar um arquivo PCH que se adaptará às diferentes variações dos cabeçalhos incluídos em cada unidade. O desempenho não será tão bom quanto uma configuração PCH adequada, mas será significativamente melhor do que se o PCH não fosse usado.
Truque # 5 do TwineCompile – Otimizando o layout do seu projeto
Ou, colocando o truque de outra forma – minimizando o número de arquivos que precisam ser compilados quando uma alteração é feita, mas equilibrando isso com o tempo necessário para vincular.
Uma tática comum usada para otimizar os tempos de compilação do C ++ é dividir os projetos em várias bibliotecas ou pacotes pequenos. A ideia é que quando qualquer código for alterado, apenas alguns arquivos neste projeto precisarão ser recompilados. A biblioteca recompilada pode apenas ser vinculada novamente a outras bibliotecas para formar o resultado final.
Existem dois motivos pelos quais isso costuma ser uma má ideia, especialmente se você estiver usando o TwineCompile:
- Você está trocando o tempo de compilação com o tempo de link. O conselho que recomenda essa abordagem é geralmente orientado para compiladores C ++ mais lentos, como o gcc, onde o tempo de link é muito mais rápido do que os tempos de compilação muito lentos. Portanto, pode ser útil transferir o trabalho para o vinculador. Os compiladores C ++ Builder (CLANG e Classic) são bastante rápidos para compiladores C ++, portanto, adicionar 15 etapas de link para evitar a compilação de 30 arquivos C ++ geralmente resulta em uma perda significativa de desempenho.
- A vinculação é um processo serial. A compilação é paralela. Quando você usa TwineCompile, os arquivos C ++ são compilados em paralelo, portanto, quanto mais unidades puderem ser compiladas simultaneamente, maior será o desempenho. Um único projeto com 200 unidades C ++ e uma única etapa de link construirá muitas vezes mais rápido do que 10 projetos com 20 unidades C ++, cada um com sua própria etapa de link.
Como acontece com a maioria das coisas na vida – há uma compensação em que uma estrutura de projeto dividida faz sentido. Infelizmente, não existe uma resposta certa para como um projeto deve ser estruturado, então vou deixar você com as seguintes diretrizes:
- Minimize o número de arquivos que precisam ser compilados para qualquer alteração na fonte.
- Minimize o número de bibliotecas, pacotes ou aplicativos que precisam ser vinculados. Mesmo as bibliotecas estáticas, embora sejam relativamente rápidas de vincular, têm uma sobrecarga.
- Maximize seus recursos de processador. O vinculador usará apenas um núcleo, 16 arquivos C ++ em um processador de 8 núcleos + HT usará todos os 16 núcleos lógicos. Portanto, a compilação desses 16 arquivos pode usar 16x mais recursos do que o vinculador.
Truque # 6 – Compilar SORTA
Um dos recursos mais poderosos do TwineCompile é seu sistema de compilação automática de plano de fundo. Essencialmente, esse recurso compila automaticamente seus arquivos de código-fonte modificados em segundo plano, de forma que, quando você clicar em Criar ou Executar, não haja arquivos para compilar, tudo está atualizado e o processo de construção só precisa vincular o aplicativo.
Ao contrário de muitos dos truques acima, este não está diretamente vinculado a tornar o processo de compilação ou construção mais rápido, mas visa reduzir ou mesmo eliminar a necessidade de compilar o código-fonte.
Para habilitar o SORTA Compile, abra as opções do TwineCompile, vá para a seção SORTA Compile e selecione a opção Habilitar SORTA Compile:
Existem vários gatilhos que são usados para invocar essa funcionalidade, incluindo quando uma unidade é salva, quando a guia do editor muda ou quando um arquivo é modificado e não é tocado por um período de tempo.
Usar SORTA Compile efetivamente requer um ajuste no fluxo de trabalho de codificação, mas pode fornecer enormes benefícios para o processo de evolução de projeto tradicional de quatro etapas: Editar, Compilar, Executar, Testar, repetir.
Truque # 7 do TwineCompile – Vinculação estática versus dinâmica
Se você aplicar os truques mencionados acima aos seus projetos, provavelmente descobrirá que começará a esperar pelo vinculador o tempo todo. Esperar pelo compilador desaparecerá completamente. Isso é uma coisa boa e ruim. Bom porque isso
significa que você está economizando todo esse tempo, o que é ruim porque não há muito mais que você possa fazer para otimizar o desempenho de compilação.
Com isso dito, alguns aplicativos podem ser reestruturados para colocar diferentes partes da funcionalidade em DLLs separadas que são carregadas pelo aplicativo em tempo de execução. Isso significa que, quando alterações de código são feitas em uma determinada parte do aplicativo, apenas esse código específico é compilado e vinculado a seu próprio arquivo DLL. O restante do aplicativo não precisa ser reconstruído porque está vinculado a essa DLL em tempo de execução.
Obviamente, essa abordagem adiciona a sobrecarga de implantação e gerenciamento de arquivos DLL extras que precisam ser agrupados com o aplicativo, mas a economia no desempenho de construção pode valer a pena a sobrecarga extra.
Truque # 6 – Hardware
Nosso último truque é um truque antigo e bem conhecido, geralmente conhecido como “jogar o hardware no problema”. Enquanto o hardware mais novo e mais rápido no passado fornecia apenas pequenos benefícios, os avanços de hardware mais recentes, juntamente com a capacidade do TwineCompile de maximizar o uso dos recursos do sistema, podem fornecer alguns benefícios significativos.
Existem duas áreas principais que devem ser focadas em:
1. Desempenho do disco
Isso significa drives SSD usando conexões NVMe / PCIe. Os SSDs SATA são bons, mas não têm o desempenho de acesso aleatório dos SSDs que operam no barramento PCIe.
Os fusos são definitivamente um não-não. Se seus projetos, diretórios temporários, sistema operacional ou caminho de instalação do C ++ Builder estiverem em um eixo, seu desempenho de compilação será péssimo.
2. núcleos da CPU
O desempenho de um único núcleo em linha reta para compilar C ++ é menos útil atualmente do que ter muitos núcleos. Vá para o número máximo de núcleos disponíveis.
Os processadores AMD Threadripper com 64 núcleos (128 threads) são ideais para compilar C ++ no C ++ Builder com TwineCompile. Observe que, para um processador como este, se você tiver menos de 128 arquivos C ++ em seu projeto, estará desperdiçando recursos da CPU – isso volta ao ponto que fizemos no truque nº 5 sobre como otimizar o layout do seu projeto para maximizar o uso da CPU recursos compilando muitos arquivos no mesmo projeto.
Pensamentos finais
Percorremos um longo caminho desde os velhos tempos da compilação em C ++, quando as compilações demoravam muito e não havia nada que pudesse ser feito a respeito. Foram desenvolvidas ferramentas e técnicas que fazem uma diferença significativa em projetos de todos os tamanhos. Cobrimos vários deles neste artigo e esperamos que você seja capaz de aplicá-los aos seus próprios projetos para tornar sua experiência de desenvolvimento C ++ mais rápida, simples e fácil.
RAD Studio C ++ Builder, por que não experimentá-lo hoje?
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition