Esse princípio no pilar de sustentabilidade do Google Cloud Framework bem arquitetado fornece recomendações para escrever softwares que minimizem o consumo de energia e a carga do servidor.
Visão geral do princípio
Ao seguir as práticas recomendadas para criar aplicativos na nuvem, você otimiza a energia utilizada pelos recursos infraestrutura em nuvem: IA, computação, armazenamento e rede. Você também ajuda a reduzir os requisitos de água dos data centers e a energia que os dispositivos do usuário final consomem ao acessar seus aplicativos.
Para criar um software com eficiência energética, é preciso integrar considerações de sustentabilidade em todo o ciclo de vida do software, desde o design e o desenvolvimento até a implantação, a manutenção e o arquivamento. Para orientações detalhadas sobre como usar a IA para criar software que minimize o impacto ambiental das cargas de trabalho na nuvem, consulte o e-book Google Cloud , Crie software de forma sustentável.
Recomendações
As recomendações nesta seção são agrupadas nas seguintes áreas de foco:
- Minimize o trabalho computacional: prefira um código simples e focado que elimine a lógica redundante e evite computações desnecessárias ou o aumento de recursos.
- Use algoritmos e estruturas de dados eficientes: escolha algoritmos eficientes em termos de tempo e memória que reduzam a carga da CPU e minimizem o uso da memória.
- Otimize as operações de computação e dados: desenvolva com o objetivo de usar com eficiência todos os recursos disponíveis, incluindo CPU, memória, E/S de disco e rede. Por exemplo, ao substituir loops ocupados por lógica orientada a eventos, você evita a sondagem desnecessária.
- Implemente a otimização de front-end: para reduzir a energia consumida pelos dispositivos do usuário final, use estratégias como minimização, compactação e carregamento lento de imagens e recursos.
Minimizar o trabalho computacional
Para escrever um software com eficiência energética, é preciso minimizar a quantidade total de trabalho computacional realizado pelo aplicativo. Cada instrução desnecessária, loop redundante e recurso extra consome energia, tempo e recursos. Use as recomendações a seguir para criar um software que execute cálculos mínimos.
Escrever código simples e focado
Para escrever o mínimo de código essencial para alcançar os resultados necessários, use as seguintes abordagens:
- Elimine a lógica redundante e o excesso de recursos: escreva um código que execute apenas as funções essenciais. Evite recursos que aumentam a sobrecarga e a complexidade computacionais, mas não oferecem valor mensurável aos usuários.
- Refatorar: para melhorar a eficiência energética ao longo do tempo, audite regularmente seus aplicativos para identificar recursos não utilizados. Tome medidas para remover ou refatorar esses recursos conforme apropriado.
- Evite operações desnecessárias: não calcule um valor nem execute uma ação até que o resultado seja necessário. Use técnicas como a avaliação preguiçosa, que atrasa os cálculos até que um componente dependente no aplicativo precise da saída.
- Priorize a legibilidade e a reutilização do código: escreva um código legível e reutilizável. Essa abordagem minimiza a duplicação e segue o princípio de não se repita (DRY), que pode ajudar a reduzir as emissões de carbono do desenvolvimento e da manutenção de software.
Usar o armazenamento em cache de back-end
O armazenamento em cache no back-end garante que um aplicativo não execute o mesmo trabalho repetidamente. Uma alta proporção de ocorrência em cache leva a uma redução quase linear no consumo de energia por solicitação. Para implementar o armazenamento em cache no back-end, use as seguintes técnicas:
- Armazenar dados frequentes em cache: armazene dados acessados com frequência em um local de armazenamento temporário e de alta performance. Por exemplo, use um serviço de armazenamento em cache na memória, como o Memorystore. Quando um aplicativo recupera dados de um cache, o volume de consultas de banco de dados e operações de E/S de disco é reduzido. Consequentemente, a carga nos bancos de dados e servidores no back-end diminui.
- Armazenar respostas da API em cache: para evitar chamadas de rede redundantes e caras, armazene em cache os resultados de solicitações frequentes da API.
- Priorize o armazenamento em cache na memória: para eliminar operações lentas de E/S de disco e consultas complexas de banco de dados, armazene dados em memória de alta velocidade (RAM).
- Selecione as estratégias de gravação em cache adequadas:
- A estratégia de gravação direta garante que os dados sejam gravados de forma síncrona no cache e no armazenamento permanente. Essa estratégia aumenta a probabilidade de ocorrências em cache, para que o armazenamento persistente receba menos solicitações de leitura que consomem muita energia.
- A estratégia de write-back (write-behind) melhora o desempenho de aplicativos com muitas gravações. Os dados são gravados primeiro no cache, e o banco de dados é atualizado de forma assíncrona mais tarde. Essa estratégia reduz a carga de gravação imediata em bancos de dados mais lentos.
- Use políticas de remoção inteligentes: mantenha o cache eficiente e com poucos dados. Para remover dados desatualizados ou de baixa utilidade e maximizar o espaço disponível para dados solicitados com frequência, use políticas como time to live (TTL), menos recentemente usado (LRU) e menos frequentemente usado (LFU).
Usar algoritmos e estruturas de dados eficientes
Os algoritmos e as estruturas de dados escolhidos determinam a complexidade computacional bruta do seu software. Ao selecionar algoritmos e estruturas de dados adequados, você minimiza o número de ciclos de CPU e operações de memória necessárias para concluir uma tarefa. Menos ciclos de CPU e operações de memória levam a um menor consumo de energia.
Escolher algoritmos para complexidade de tempo ideal
Priorize algoritmos que alcançam o resultado necessário no menor tempo possível. Essa abordagem ajuda a reduzir a duração do uso de recursos. Para selecionar algoritmos que otimizam o uso de recursos, use as seguintes abordagens:
- Foco na redução da complexidade: para avaliar a complexidade, vá além das métricas de tempo de execução e considere a complexidade teórica do algoritmo. Por exemplo, quando comparada à ordenação por bolha, a ordenação por fusão reduz significativamente a carga computacional e o consumo de energia em grandes conjuntos de dados.
- Evite trabalho redundante: use funções integradas e otimizadas na linguagem de programação ou no framework escolhido. Essas funções geralmente são implementadas em uma linguagem de nível mais baixo e mais eficiente em termos de energia, como C ou C++. Assim, elas são mais bem otimizadas para o hardware subjacente em comparação com funções codificadas de maneira personalizada.
Selecionar estruturas de dados para eficiência
As estruturas de dados escolhidas determinam a velocidade com que os dados podem ser recuperados, inseridos ou processados. Essa velocidade afeta o uso da CPU e da memória. Para selecionar estruturas de dados eficientes, use as seguintes abordagens:
- Otimize para pesquisa e recuperação: para operações comuns, como verificar se um item existe ou recuperar um valor específico, prefira estruturas de dados otimizadas para velocidade. Por exemplo, mapas ou conjuntos de hash permitem pesquisas em tempo quase constante, o que é uma abordagem mais eficiente em termos de energia do que pesquisar linearmente em uma matriz.
- Minimizar a pegada de memória: estruturas de dados eficientes ajudam a reduzir a pegada de memória geral de um aplicativo. O acesso e o gerenciamento reduzidos da memória levam a um menor consumo de energia. Além disso, um perfil de memória mais eficiente permite que os processos sejam executados com mais eficiência, o que possibilita adiar upgrades de recursos.
- Use estruturas especializadas: use estruturas de dados criadas especificamente para um determinado problema. Por exemplo, use uma estrutura de dados trie para pesquisa rápida de prefixos de string e uma fila de prioridade quando precisar acessar apenas o valor mais alto ou mais baixo de maneira eficiente.
Otimizar operações de computação e dados
Ao desenvolver software, concentre-se no uso eficiente e proporcional de recursos em toda a pilha de tecnologia. Trate CPU, memória, disco e rede como recursos limitados e compartilhados. Reconheça que o uso eficiente de recursos leva a reduções tangíveis nos custos e no consumo de energia.
Otimizar a utilização da CPU e o tempo ocioso
Para minimizar o tempo que a CPU passa em um estado ativo e de consumo de energia sem realizar um trabalho significativo, use as seguintes abordagens:
- Prefira a lógica orientada a eventos em vez da pesquisa: substitua loops ocupados ou verificação constante (pesquisa) que consomem muitos recursos por uma lógica orientada a eventos. Uma arquitetura orientada a eventos garante que os componentes de um aplicativo operem apenas quando são acionados por eventos relevantes. Essa abordagem permite o processamento sob demanda, o que elimina a necessidade de sondagem com uso intensivo de recursos.
- Evite alta frequência constante: escreva um código que não force a CPU a operar constantemente na frequência mais alta. Para minimizar o consumo de energia, os sistemas inativos precisam entrar em estados de baixo consumo de energia ou modos de suspensão.
- Use o processamento assíncrono: para evitar que as linhas de execução sejam bloqueadas durante tempos de espera ociosos, use o processamento assíncrono. Essa abordagem libera recursos e leva a uma maior utilização geral de recursos.
Gerenciar a memória e a E/S de disco com eficiência
O uso ineficiente da memória e do disco leva a um processamento desnecessário e a um aumento no consumo de energia. Para gerenciar a memória e a E/S de maneira eficiente, use as seguintes técnicas:
- Gerenciamento estrito de memória: tome medidas para liberar proativamente recursos de memória não utilizados. Evite manter objetos grandes na memória por mais tempo do que o necessário. Essa abordagem evita gargalos de desempenho e reduz a energia consumida para acesso à memória.
- Otimize a E/S do disco: reduza a frequência das interações de leitura e gravação do aplicativo com recursos de armazenamento permanente. Por exemplo, use um buffer de memória intermediário para armazenar dados. Grave os dados no armazenamento permanente em intervalos fixos ou quando o buffer atingir um determinado tamanho.
- Operações em lote: consolide operações de disco pequenas e frequentes em operações em lote maiores e em menor número. Uma operação em lote consome menos energia do que muitas transações individuais e pequenas.
- Use a compactação: reduza a quantidade de dados gravados ou lidos dos discos aplicando técnicas adequadas de compactação de dados. Por exemplo, para compactar dados armazenados no Cloud Storage, use a transcodificação descompactadora.
Minimizar o tráfego de rede
Os recursos de rede consomem muita energia durante as operações de transferência de dados. Para otimizar a comunicação de rede, use as seguintes técnicas:
- Minimizar o tamanho da carga útil: crie APIs e aplicativos para transferir apenas os dados necessários para uma solicitação. Evite buscar ou retornar estruturas JSON ou XML grandes quando apenas alguns campos são necessários. Verifique se as estruturas de dados retornadas são concisas.
- Reduza as viagens de ida e volta: para diminuir o número de viagens de ida e volta da rede necessárias para concluir uma ação do usuário, use protocolos mais inteligentes. Por exemplo, prefira HTTP/3 em vez de HTTP/1.1, escolha GraphQL em vez de REST, use protocolos binários e consolide chamadas de API. Ao reduzir o volume de chamadas de rede, você diminui o consumo de energia dos servidores e dos dispositivos do usuário final.
Implementar a otimização de front-end
A otimização de front-end minimiza os dados que os usuários finais precisam baixar e processar, o que ajuda a reduzir a carga nos recursos dos dispositivos deles.
Minimizar código e recursos
Quando os usuários finais precisam fazer o download e processar recursos menores e mais eficientes estruturados, os dispositivos consomem menos energia. Para minimizar o volume de download e a carga de processamento nos dispositivos dos usuários finais, use as seguintes técnicas:
- Minimização e compactação: para arquivos JavaScript, CSS e HTML, remova caracteres desnecessários, como espaços em branco e comentários, usando ferramentas de minimização adequadas. Verifique se arquivos como imagens estão compactados e otimizados. É possível automatizar a minimização e a compressão de recursos da Web usando um pipeline de CI/CD.
- Carregamento lento: carregue imagens, vídeos e recursos não essenciais somente quando eles forem realmente necessários, como quando esses elementos rolam para a janela de visualização de uma página da Web. Essa abordagem reduz o volume de transferência de dados inicial e a carga de processamento nos dispositivos dos usuários finais.
- Pacotes JavaScript menores: elimine o código não usado dos pacotes JavaScript usando agrupadores de módulos modernos e técnicas como tree shaking. Essa abordagem resulta em arquivos menores que carregam mais rápido e usam menos recursos do servidor.
- Cache do navegador: use cabeçalhos de cache HTTP para instruir o navegador do usuário a armazenar recursos estáticos localmente. O cache do navegador ajuda a evitar downloads repetidos e tráfego de rede desnecessário em visitas subsequentes.
Priorizar uma experiência do usuário (UX) leve
O design da interface do usuário pode ter um impacto significativo na complexidade computacional para renderizar o conteúdo do front-end. Para criar interfaces de front-end que ofereçam uma UX leve, use as seguintes técnicas:
- Renderização eficiente: evite manipulação frequente e com uso intensivo de recursos do Modelo de objeto de documentos (DOM). Escreva um código que minimize a complexidade de renderização e elimine a nova renderização desnecessária.
- Padrões de design leves: quando apropriado, prefira sites estáticos ou Progressive Web Apps (PWAs). Esses sites e apps carregam mais rápido e exigem menos recursos do servidor.
- Acessibilidade e performance: sites responsivos e de carregamento rápido costumam ser mais sustentáveis e acessíveis. Um design otimizado e sem poluição visual reduz os recursos consumidos quando o conteúdo é renderizado. Sites otimizados para performance e velocidade podem ajudar a gerar mais receita. De acordo com um estudo da Deloitte e do Google, Milliseconds Make Millions, uma melhoria de 0,1 segundo (100 ms) na velocidade do site leva a um aumento de 8,4% nas conversões para sites de varejo e de 9,2% no valor médio do pedido.