Código verde y abedules. Principios básicos del código verde en desarrollo





Hola. Mi nombre es Stas, en Domclick superviso el desarrollo de servicios administrativos para préstamos hipotecarios en Sberbank.



Recientemente, en todo tipo de informes y podcasts, a menudo me he encontrado con el término "Código Verde". Habiendo rebuscado en Internet y habiendo estudiado este tema, me di cuenta de que este término describe un conjunto de técnicas en el desarrollo y diseño de aplicaciones que pueden reducir el consumo de energía de los equipos en los que se ejecuta este código.



Más o menos esta pregunta suele ser desconcertada por los desarrolladores de aplicaciones móviles, principalmente porque el dispositivo en el que se ejecutará su código tiene una capacidad de batería limitada.



El tema se ha vuelto bastante "exagerado", y decidí averiguar cómo se pueden reflejar exactamente los principios de "verde" en el desarrollo WEB.



Principios básicos para escribir "código verde"



Después de leer muchos informes y artículos sobre este tema, destacaría los siguientes aspectos del desarrollo de aplicaciones que afectan el consumo de energía:



1) Simplificación y optimización de algoritmos



Como se mencionó anteriormente, la ejecución del código debería conducir a un consumo mínimo de energía. El código optimizado se ejecutará más rápido y, por lo tanto, requerirá menos costos de procesamiento y enfriamiento del equipo.



Intentemos calcular la diferencia en el consumo de energía para ejecutar una operación específica en el código: la clasificación clásica de una lista. Exageraré deliberadamente la situación en el ejemplo dado para mostrar la diferencia con más contraste.



Tomemos una especie de burbuja. Esta es probablemente una de las formas más subóptimas. Muy adecuado para nosotros. Calculemos la clasificación de la lista y veamos cómo afectó el consumo de energía del MacBook. Primero, simulemos la matriz de datos y la propia lógica de clasificación de burbujas:



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 el impacto de la ejecución del código en el consumo de energía, utilicé el sistema de monitoreo iStat Menus 6 (https://bjango.com/mac/istatmenus/). Conecté mi MacBook a la red, cerré todas las aplicaciones de terceros, esperé un cierto tiempo para cargar la batería y comencé a clasificar:



Gráfico de







consumo de energía al realizar la clasificación de burbujas: es visible un salto pronunciado en el consumo de energía que dura 305 segundos. Fue causado por la ejecución de nuestra solicitud no óptima. Además, la energía gastada durante 5 minutos (305 segundos)



P = (W2 – W1) × 305 = (17,29 [ ] – 2,9 [ ]) × 305 = 14,39 × 305 = 4389 = 0,0012 * .



Ahora digamos que este código llegó accidentalmente a un servidor de producto industrial (supongamos que el consumo de energía adicional en el servidor será el mismo que en mi MacBook, y la dependencia es directamente proporcional) y comenzó a ejecutarse con una frecuencia de 1 cada 10 segundos. A continuación, un año recibimos más energía:



365 × 24 × 3600 /10 × 0,0012 * = 3 784,32 *.



Suponga que el centro de datos que aloja el servidor recibe energía de una sala de calderas que utiliza madera de abedul como combustible. Al quemar 1 m 3 de madera de abedul, se liberan 1900 kW * h / m 3 de energía. Por supuesto, la eficiencia de la caldera no es 100%, y si se tiene que el 75%, obtenemos: . Si tomamos un árbol como un cilindro regular, cuyo volumen es



(3 784,32 / 1900) / 0,75 = 2,66 3







V = Pi × R2 × H



donde R es el radio del tronco del árbol, tomémoslo como 0,12 metros (valor promedio),

H es la altura del tronco del árbol, tomémoslo como 3 metros (valor promedio).



luego obtenemos: Esto significa que habrá madera en un metro cúbico . Necesitamos un año para impulsar nuestro guión . A modo de comparación, realicé la misma clasificación utilizando el método de clasificación estándar de Python ( ). Gráfico de consumo de energía al realizar la clasificación estándar en Python: aplicando la misma lógica de cálculo (la duración máxima fue de 10 segundos), obtenemos: En un año obtenemos (asumiendo que la operación se realiza 1 vez en 10 segundos) O:



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 .



Por supuesto, hay muchas suposiciones en este ejemplo y la clasificación de burbujas rara vez se realiza. Pero los números resultantes me parecieron interesantes



2) Utilice el modelo impulsado por eventos de la aplicación siempre que sea posible



El punto es que la mayoría de los procesadores admiten múltiples "estados" de consumo de energía. En el caso de que el kernel no esté ocupado con ningún cálculo, el sistema operativo lo pone en un estado de "suspensión", en el que el procesador consume mucha menos energía.



Espectro de estados (optimización energética):







puede leer más sobre esto aquí .



Muy a menudo, existe una situación en la que se debe ejecutar alguna lógica de aplicación cuando ocurre un evento determinado. Y para saber que ha ocurrido este evento, el servicio interesado en recibir esta información suele sondear periódicamente al servicio que almacena el hecho de que este evento se ha completado. Por temporizador. Además, la inmensa mayoría de las solicitudes reciben una respuesta negativa, es decir, el 99% de las solicitudes, de hecho, no son necesarias.



Sería correcto transmitir el evento correspondiente a la cola y leer el hecho de su ocurrencia a todos los servicios interesados.




Espectro de estados (optimización energética):





Otro ejemplo es la interacción de los componentes de la aplicación de front-end y back-end. Si el frente necesita cambiar su estado dependiendo de los datos en la base de datos, a veces las solicitudes se envían periódicamente al backend, creando una carga adicional innecesaria. Aunque es posible informar al frente sobre un cambio en el estado de los datos necesarios a través del servidor de socket.



Si bien los sockets también pueden confundirse, aquí hay un ejemplo de código "incorrecto":



while(true)
{
        // Read data
        result = recv(serverSocket, buffer, bufferLen, 0);

        // Handle data  
        if(result != 0)
        {
                HandleData(buffer);
        }

        // Sleep and repeat
        Sleep(1000);
}


Se puede ver que incluso si no llegan datos al socket, el código se ejecutará cada 1000 segundos, desperdiciando una energía preciosa.



Lo mismo se puede escribir de una manera ligeramente diferente y se gastará menos energía:



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: «»



Si los datos todavía se utilizan, pero rara vez, es mejor no mostrarlos de forma predeterminada, sino mostrarlos solo haciendo clic en el botón "Mostrar información detallada".



Un ejemplo simple que ilustra este principio: mostrar listas de objetos de datos (solicitudes, usuarios, puntos de venta, almacenes, oficinas), siempre que el escenario para usar el formulario aún implique encontrar el objeto deseado.



Un ejemplo de una mala interfaz :







la página muestra una enorme lista de tareas (divididas en "páginas"), pero el usuario seguirá buscando un cliente específico (de acuerdo con alguna lógica en su cabeza) en la barra de búsqueda en la parte superior. ¿Por qué desperdiciar recursos obteniendo una lista de tareas pendientes?



El mismo escenario, implementado de manera diferente:



Ejemplo de una interfaz "verde" :







La lógica de selección de cliente se ha trasladado al sistema, por defecto, los datos innecesarios no se solicitan "por costumbre". Esta opción, además de los ecologistas, y la ciberseguridad será aplaudida ferozmente.



4) Refactorización



La refactorización casi siempre es útil. Pero en este contexto, es necesario para un propósito simple: desechar el código innecesario (basura) o simplificar el existente para reducir el consumo de energía.



Muchas aplicaciones que se han desarrollado durante más de tres años acumulan cientos de líneas de código no utilizado o que funciona de manera impredecible que quedan de funciones previamente implementadas (y posiblemente ya cortadas). A veces, este código incluso se ejecuta, pero no se requiere el resultado de su trabajo.



La auditoría y la refactorización periódicas reducirán la cantidad de dicho código, aunque probablemente no lo eliminará por completo.



Por ejemplo, al refactorizar regularmente uno de nuestros servicios (dentro de la cuota técnica de horas de trabajo), encontramos esto:



Ejemplo de refactorización :







crm_deal_id- identificador de la operación hipotecaria en el sistema antiguo. Ahora ya no es necesario, pero el código aún se está comprobando para obtenerlo y llamando a una función adicional delete_deal_chat_telephonyque realiza muchas otras acciones.



Todo esto se puede eliminar sin perder funcionalidad.



5) Utilice lenguajes de programación de bajo nivel para aplicaciones de alta carga



Obviamente, en la mayoría de los casos, las aplicaciones escritas en lenguajes de bajo nivel son más eficientes energéticamente. Tiene sentido reescribir un servicio cargado en Python (si realiza una operación simple) en C / C +. Será más rápido y ecológico.



Es cierto que a menudo no tenemos los conocimientos necesarios para escribir lógica en esos lenguajes.



6) Operaciones de E / S de grupo



Los sistemas de almacenamiento, como los procesadores, también tienen diferentes estados de energía.

El modo de suspensión consume mucha menos energía que el modo de funcionamiento en caliente. Esto es especialmente cierto para los sistemas de almacenamiento / discos duros.



Si la aplicación puede agrupar los datos escritos en el disco y acceder al disco no constantemente, sino en ciertos períodos de tiempo, entonces será más eficiente energéticamente, ya que durante el período de "inactivo" el sistema operativo enviará el disco a "hibernación".



7) Uso de sistemas de almacenamiento de registros que consuman menos energía



Es una buena práctica utilizar almacenamiento "caliente" y "frío". Por ejemplo, tiene sentido almacenar los registros de la última semana en la forma indexada de cocción "caliente", ya que la probabilidad de acceder a ellos será bastante alta. Los registros más largos se pueden almacenar en sistemas de almacenamiento más baratos y que consumen menos energía.



¿Qué tal a escala industrial?



Arriba, cubrimos las técnicas básicas para trabajar con código para asegurar su eficiencia energética. Pero incluso seguir la mayoría de estas reglas producirá ahorros muy modestos que serán difíciles de visualizar. Por supuesto, si las listas no se ordenan por el método de la burbuja en las ventas, el



desarrollo intencionado de la funcionalidad para la implementación de la gestión de documentos electrónicos dará un efecto mucho mayor.



Una de las actividades de los equipos de Domclick es optimizar y simplificar el proceso de obtención de una hipoteca. Y en este proceso hipotecario, en la etapa final, se preparan muchos documentos en papel. Y en varias copias. Una copia para el vendedor, otra para el comprador y otra para el archivo bancario.



Me complace saber que Domclick está haciendo un gran esfuerzo para eliminar esta práctica viciosa y transferir todo el flujo de documentos a formato electrónico. Este año, una parte importante de las transacciones hipotecarias ya se han digitalizado por completo (solo se imprimió un documento: una solicitud para la emisión de un UKEP, una firma electrónica criptográfica mejorada). Todos los demás documentos fueron firmados por este UKEP y no se gastó papel en ellos.



Esta iniciativa ya ha ahorrado más de 67.491.108 hojas de papel. ¡En abedules, hay unos 23.000 árboles!



¡Proteger el medio ambiente!



Enlaces para los interesados:

  1. Green IT: datos disponibles y pautas para reducir el consumo de energía en sistemas de TI / Ardito L. Morisio M… - En: COMPUTACIÓN SOSTENIBLE. - ISSN 2210-5379. - STAMPA
  2. Understanding Green Software Development: A conceptual Framework /Luca Ardito, Giuseppe Procaccianti, Marco Torchiano, Antonio Vetro
  3. Green SW Engineering:Ideas for including Energy Efficiency into your Softwar Projects/Gerald Kaefer



All Articles