Olá. Meu nome é Stas, na Domclick eu supervisiono o desenvolvimento de serviços administrativos para empréstimos hipotecários no Sberbank.
Recentemente, em todos os tipos de relatórios e podcasts, frequentemente me deparei com o termo "Código Verde". Tendo vasculhado a Internet e estudado este tópico, percebi que este termo descreve um conjunto de técnicas no desenvolvimento e design de aplicações que podem reduzir o consumo de energia dos equipamentos nos quais este código é executado.
Mais ou menos essa questão costuma ser confundida pelos desenvolvedores de aplicativos móveis, principalmente porque o dispositivo no qual seu código será executado tem capacidade limitada de bateria.
O tópico se tornou bastante "exagero", e decidi descobrir como exatamente os princípios do "verde" podem ser refletidos no desenvolvimento da WEB.
Princípios básicos para escrever "código verde"
Depois de ler muitos relatórios e artigos sobre este tópico, gostaria de destacar os seguintes aspectos do desenvolvimento de aplicativos que afetam o consumo de energia:
1) Simplificação e otimização de algoritmos
Conforme mencionado acima, a execução do código deve levar a um consumo mínimo de energia. O código otimizado será executado com mais rapidez e, portanto, exigirá menos custos de processamento e resfriamento do equipamento.
Vamos tentar calcular a diferença no consumo de energia para executar uma operação específica no código - a classificação clássica de uma lista. Vou exagerar deliberadamente a situação no exemplo dado a fim de mostrar a diferença com mais contraste.
Vamos dar uma espécie de bolha. Esta é provavelmente uma das formas menos ideais. Muito adequado para nós. Vamos calcular a classificação da lista e ver como isso afetou o consumo de energia do MacBook. Primeiro, vamos simular a matriz de dados e a própria lógica de classificação de bolha:
from random import randint
def bubble(array):
for i in range(productNumber-1):
for j in range(productNumber-i-1):
if array[j] > array[j+1]:
buff = array[j]
array[j] = array[j+1]
array[j+1] = buff
productNumber = 60000
products = []
for i in range(productNumber):
products.append(randint(1, 1000))
bubble(products)
print(products)
Para medir o impacto da execução do código no consumo de energia, usei o sistema de monitoramento iStat Menus 6 (https://bjango.com/mac/istatmenus/). Eu conectei meu MacBook à rede, fechei todos os aplicativos de terceiros, esperei um certo tempo para carregar a bateria e comecei a classificar:
Gráfico de
consumo de energia ao executar a classificação por bolha: Você pode ver um salto pronunciado no consumo de energia com duração de 305 segundos. Foi causado pela execução de nossa solicitação não ideal. Além disso, a energia gasta por 5 minutos (305 segundos)
P = (W2 – W1) × 305 = (17,29 [ ] – 2,9 [ ]) × 305 = 14,39 × 305 = 4389 = 0,0012 * .
Agora digamos que este código acidentalmente chegou a um servidor de produto industrial (vamos supor que o consumo de energia adicional no servidor será o mesmo do meu MacBook e a dependência é diretamente proporcional) e começou a ser executado com uma frequência de 1 vez a cada 10 segundos. Em seguida, um ano temos mais energia:
365 × 24 × 3600 /10 × 0,0012 * = 3 784,32 *.
Suponha que o data center que hospeda o servidor receba energia de uma sala de caldeira que usa madeira de bétula como combustível. Ao queimar 1 m 3 de madeira de bétula, são liberados 1.900 kW * h / m 3 de energia. Claro, a eficiência da caldeira não é 100%, e se nós levá-la para 75%, temos: . Se tomarmos uma árvore como um cilindro regular, o volume do qual é
(3 784,32 / 1900) / 0,75 = 2,66 3
V = Pi × R2 × H
onde R é o raio do tronco da árvore, vamos considerá-lo como 0,12 metros (valor médio),
H é a altura do tronco da árvore, vamos considerá-lo como 3 metros (valor médio).
então temos: Isso significa que haverá madeira em um metro cúbico . Precisamos de um ano para potencializar nosso script . Para comparação, executei a mesma classificação usando o método de classificação Python padrão ( ). Gráfico de consumo de energia ao realizar a classificação padrão em Python: Aplicando a mesma lógica de cálculo (a duração do pico foi de 10 segundos), obtemos: Em um ano, obtemos (assumindo que a operação seja realizada 1 vez em 10 segundos) Ou:
V = 3,14 × 0,0144 × 3 = 0,14 3
1 / 0,14 = 7,14
2,66 3 × 7,14 = 19
.sort()
P = (W2 – W1) × 10 = (3,51 [ ] – 2,9 [ ]) × 10 = 6,1 = 0,0000016 *
365 × 24 × 3600 /10 × 0,0000016 * = 5,05 *
5,05 / 1900 / 0,75 × 7,14 = 0,025 .
Claro, há muitas suposições neste exemplo e a classificação por bolha raramente é feita. Mas os números resultantes pareciam interessantes para mim
2) Use o modelo orientado a eventos do aplicativo sempre que possível
O ponto é que a maioria dos processadores suporta vários "estados" de consumo de energia. Caso o kernel não esteja ocupado com nenhum cálculo, o sistema operacional o coloca em um estado de “hibernação”, no qual o processador consome muito menos energia.
Espectro de estados (otimização de energia):
Você pode ler mais sobre isso aqui .
Freqüentemente, há uma situação em que alguma lógica de aplicativo deve ser executada quando um determinado evento ocorre. E para saber se esse evento ocorreu, o serviço interessado em receber essa informação costuma consultar periodicamente o serviço que armazena o fato de que esse evento foi concluído. Por cronômetro. Além disso, a esmagadora maioria das solicitações recebe uma resposta negativa, ou seja, 99% das solicitações, de fato, não são necessárias.
Seria correto transmitir o evento correspondente para a fila e ler o fato de sua ocorrência para todos os serviços interessados.
Espectro de estados (otimização de energia):

Outro exemplo é a interação de componentes de aplicativo front-end e back-end. Se o front precisa mudar seu estado dependendo dos dados no banco de dados, às vezes as solicitações são enviadas periodicamente para o back-end, criando uma carga adicional desnecessária. Embora seja possível informar a frente sobre uma mudança no estado dos dados necessários através do servidor de soquete.
Embora os soquetes também possam ser confundidos, aqui está um exemplo de código "ruim":
while(true)
{
// Read data
result = recv(serverSocket, buffer, bufferLen, 0);
// Handle data
if(result != 0)
{
HandleData(buffer);
}
// Sleep and repeat
Sleep(1000);
}
Pode-se perceber que mesmo que nenhum dado chegue ao socket, o código ainda será executado a cada 1000 segundos, desperdiçando energia preciosa.
A mesma coisa pode ser escrita de uma forma ligeiramente diferente e menos energia será gasta:
WSANETWORKEVENTS NetworkEvents;
WSAEVENT wsaSocketEvent;
wsaSocketEvent = WSACreateEvent();
WSAEventSelect(serverSocket,
wsaSocketEvent, FD_READ|FD_CLOSE);
while(true)
{
// Wait until data will be available in
the socket
WaitForSingleObject(wsaSocketEve
nt, INFINITE);
// Read data
result = recv(serverSocket, buffer,
bufferLen, 0);
// Handle data
if(result != 0)
{
HandleData(buffer);
}
}
3) UI/UX: «»
Se os dados ainda são usados, mas raramente, então é melhor não exibi-los por padrão, mas exibi-los apenas clicando no botão "Mostrar informações detalhadas".
Um exemplo simples que ilustra esse princípio: exibir listas de objetos de dados (solicitações, usuários, pontos de venda, depósitos, escritórios), desde que o cenário de utilização do formulário ainda implique a localização do objeto desejado.
Um exemplo de interface ruim :
a página exibe uma lista enorme de tarefas (dividida em "páginas"), mas o usuário ainda irá procurar por um cliente específico (de acordo com alguma lógica em sua cabeça) na barra de pesquisa no topo. Por que desperdiçar recursos obtendo uma lista de tarefas?
O mesmo cenário, implementado de forma diferente:
Exemplo de uma interface "verde" :
A lógica de seleção do cliente foi movida para o sistema; por padrão, dados desnecessários não são solicitados "por hábito". Esta opção, além de ambientalistas e cibersegurança, será fortemente aplaudida.
4) Refatoração
A refatoração quase sempre é útil. Mas, neste contexto, é necessário para um propósito simples: jogar fora código desnecessário (lixo) ou simplificar o existente para reduzir o consumo de energia.
Muitos aplicativos que têm sido desenvolvidos por mais de três anos acumulam centenas de linhas de código não utilizado ou imprevisivelmente funcional que sobrou de funções previamente implementadas (e possivelmente já cortadas). Às vezes, esse código é até executado, mas o resultado de seu trabalho não é reivindicado.
A auditoria e a refatoração periódicas reduzirão a quantidade desse código, embora provavelmente não o eliminem completamente.
Por exemplo, ao refatorar regularmente um de nossos serviços (dentro da cota técnica de horas de trabalho), encontramos o seguinte:
Exemplo de refatoração :
crm_deal_id- identificador da transação de hipoteca no sistema antigo. Agora não é mais necessário, mas o código ainda está verificando para obtê-lo e chamando uma função adicional delete_deal_chat_telephonyque executa muitas outras ações.
Tudo isso pode ser removido sem perder funcionalidade.
5) Use linguagens de programação de baixo nível para aplicativos de alta carga
Obviamente, na maioria dos casos, os aplicativos escritos em linguagens de baixo nível são mais eficientes em termos de energia. Faz sentido reescrever um serviço carregado em Python (se ele realizar uma operação simples) em C / C +. Será mais rápido e mais ecológico.
É verdade que frequentemente não temos o conhecimento necessário para escrever lógica nessas linguagens.
6) Operações de grupo I / O
Os sistemas de armazenamento, como os processadores, também têm diferentes estados de energia.
No modo "hibernar", muito menos energia é consumida do que em um estado operacional "quente". Isso é especialmente verdadeiro para sistemas de armazenamento / discos rígidos.
Se a aplicação conseguir agrupar os dados gravados no disco e acessar o disco não constantemente, mas em determinados períodos de tempo, será mais eficiente em termos energéticos, pois durante o período de “inatividade” o sistema operacional irá colocar o disco em “hibernação”.
7) Usando sistemas de armazenamento com menor consumo de energia para registros
É uma boa prática usar armazenamento "quente" e "frio". Por exemplo, faz sentido armazenar as toras da última semana na forma indexada de cozimento "quente", pois a probabilidade de acessá-las será bastante alta. Logs mais longos podem ser armazenados em sistemas de armazenamento mais baratos e com menos consumo de energia.
Que tal em escala industrial?
Acima, cobrimos as técnicas básicas para trabalhar com código para garantir sua eficiência energética. Mas, mesmo seguindo a maioria dessas regras, haverá uma economia muito modesta que será difícil de visualizar. Obviamente, se as listas não forem classificadas pelo método de bolha em vendas, o
desenvolvimento proposital de funcionalidade para a implementação do gerenciamento eletrônico de documentos terá um efeito muito maior.
Uma das atividades das equipes Domclick é otimizar e simplificar o processo de obtenção de uma hipoteca. E nesse processo de hipoteca, na fase final, muitos documentos são preparados em papel. E em várias cópias. Uma cópia para o vendedor, uma para o comprador e uma para o arquivo do banco.
Fico satisfeito em saber que o Domclick está se esforçando muito para eliminar essa prática viciosa e transferir todo o fluxo de documentos para o formato eletrônico. Este ano, uma parte significativa das transações hipotecárias já foi totalmente digitalizada (apenas um papel foi impresso: um pedido de emissão de uma UKEP, uma assinatura eletrônica criptográfica aprimorada). Todos os outros documentos foram assinados por este UKEP e nenhum papel foi gasto com eles.
A iniciativa já economizou mais de 67.491.108 folhas de papel. Em bétulas, existem cerca de 23.000 árvores!
Proteja o meio ambiente!
Links para os interessados:
- Green IT - dados disponíveis e diretrizes para redução do consumo de energia em Sistemas de TI / Ardito L.; Morisio M… - In: COMPUTAÇÃO SUSTENTÁVEL. - ISSN 2210-5379. - STAMPA
- Understanding Green Software Development: A conceptual Framework /Luca Ardito, Giuseppe Procaccianti, Marco Torchiano, Antonio Vetro
- Green SW Engineering:Ideas for including Energy Efficiency into your Softwar Projects/Gerald Kaefer