Este principio del pilar de sustentabilidad del Google Cloud Well-Architected Framework proporciona recomendaciones para escribir software que minimice el consumo de energía y la carga del servidor.
Descripción general del principio
Cuando sigues las prácticas recomendadas para compilar tus aplicaciones en la nube, optimizas la energía que utilizan los recursos de infraestructura de la nube: IA, procesamiento, almacenamiento y red. También ayudas a reducir los requisitos de agua de los centros de datos y la energía que consumen los dispositivos del usuario final cuando acceden a tus aplicaciones.
Para compilar software de bajo consumo, debes integrar consideraciones de sostenibilidad durante todo el ciclo de vida del software, desde el diseño y el desarrollo hasta la implementación, el mantenimiento y el archivo. Para obtener instrucciones detalladas sobre el uso de la IA para compilar software que minimice el impacto ambiental de las cargas de trabajo en la nube, consulta el Google Cloud libro electrónico, Build Software Sustainably.
Recomendaciones
Las recomendaciones de esta sección se agrupan en las siguientes áreas de enfoque:
- Minimiza el trabajo computacional: Favorece el código simple y enfocado que elimina la lógica redundante y evita los cálculos innecesarios o la sobrecarga de funciones.
- Usa algoritmos y estructuras de datos eficientes: Elige algoritmos eficientes en cuanto al tiempo y la memoria que reduzcan la carga de la CPU y minimicen el uso de memoria.
- Optimiza las operaciones de procesamiento y datos: Desarrolla con el objetivo de usar de manera eficiente todos los recursos disponibles, incluidos la CPU, la memoria, la E/S de disco y la red. Por ejemplo, cuando reemplazas los bucles ocupados por una lógica basada en eventos, evitas el sondeo innecesario.
- Implementa la optimización del frontend: Para reducir la energía que consumen los dispositivos del usuario final, usa estrategias como la minimización, la compresión y la carga diferida para las imágenes y los recursos.
Minimiza el trabajo computacional
Para escribir software de bajo consumo, debes minimizar la cantidad total de trabajo computacional que realiza tu aplicación. Cada instrucción innecesaria, bucle redundante y función adicional consume energía, tiempo y recursos. Usa las siguientes recomendaciones para compilar software que realice cálculos mínimos.
Escribe código simple y enfocado
Para escribir código mínimo que sea esencial para lograr los resultados requeridos, usa los siguientes enfoques:
- Elimina la lógica redundante y la sobrecarga de funciones: Escribe código que realice solo las funciones esenciales. Evita las funciones que aumentan la sobrecarga computacional y la complejidad, pero que no proporcionan un valor medible a tus usuarios.
- Refactoriza: Para mejorar la eficiencia energética con el tiempo, audita tus aplicaciones con regularidad para identificar las funciones sin usar. Toma medidas para quitar o refactorizar esas funciones según corresponda.
- Evita las operaciones innecesarias: No calcules un valor ni ejecutes una acción hasta que se necesite el resultado. Usa técnicas como la evaluación diferida, que retrasan los cálculos hasta que un componente dependiente de la aplicación necesita el resultado.
- Prioriza la legibilidad y la reutilización del código: Escribe código legible y reutilizable. Este enfoque minimiza la duplicación y sigue el principio de no te repitas (DRY), lo que puede ayudar a reducir las emisiones de carbono del desarrollo y el mantenimiento de software.
Usa el almacenamiento en caché de backend
El almacenamiento en caché de backend garantiza que una aplicación no realice el mismo trabajo de forma repetida. Una alta proporción de aciertos de caché genera una reducción casi lineal en el consumo de energía por solicitud. Para implementar el almacenamiento en caché de backend, usa las siguientes técnicas:
- Almacena en caché los datos frecuentes: Almacena los datos a los que se accede con frecuencia en una ubicación de almacenamiento temporal de alto rendimiento. Por ejemplo, usa un servicio de almacenamiento en caché en memoria como Memorystore. Cuando una aplicación recupera datos de una caché, se reduce el volumen de consultas de bases de datos y operaciones de E/S de disco. En consecuencia, disminuye la carga en las bases de datos y los servidores del backend.
- Almacena en caché las respuestas de la API: Para evitar llamadas de red redundantes y costosas, almacena en caché los resultados de las solicitudes frecuentes a la API.
- Prioriza el almacenamiento en caché en memoria: Para eliminar las operaciones lentas de E/S de disco y las consultas complejas de bases de datos, almacena los datos en la memoria de alta velocidad (RAM).
- Selecciona estrategias de escritura en caché adecuadas:
- La estrategia de escritura directa garantiza que los datos se escriban de forma síncrona en la caché y el almacén persistente. Esta estrategia aumenta la probabilidad de aciertos de caché, por lo que el almacén persistente recibe menos solicitudes de lectura que consumen mucha energía.
- La estrategia de escritura diferida (write-behind) mejora el rendimiento de las aplicaciones con muchas operaciones de escritura. Los datos se escriben primero en la caché y, luego, la base de datos se actualiza de forma asíncrona. Esta estrategia reduce la carga de escritura inmediata en las bases de datos más lentas.
- Usa políticas de expulsión inteligentes: Mantén la caché simple y eficiente. Para quitar datos obsoletos o de baja utilidad y maximizar el espacio disponible para los datos solicitados con frecuencia, usa políticas como el tiempo de actividad (TTL), el usado menos recientemente (LRU) y el usado con menor frecuencia (LFU).
Usa algoritmos y estructuras de datos eficientes
Los algoritmos y las estructuras de datos que elijas determinan la complejidad computacional sin procesar de tu software. Cuando seleccionas algoritmos y estructuras de datos adecuados, minimizas la cantidad de ciclos de CPU y operaciones de memoria que se requieren para completar una tarea. Menos ciclos de CPU y operaciones de memoria generan un menor consumo de energía.
Elige algoritmos para una complejidad temporal óptima
Prioriza los algoritmos que logran el resultado requerido en la menor cantidad de tiempo. Este enfoque ayuda a reducir la duración del uso de recursos. Para seleccionar algoritmos que optimicen el uso de recursos, usa los siguientes enfoques:
- Enfócate en reducir la complejidad: Para evaluar la complejidad, mira más allá de las métricas de tiempo de ejecución y considera la complejidad teórica del algoritmo. Por ejemplo, en comparación con la ordenación de burbujas, la ordenación por combinación reduce significativamente la carga computacional y el consumo de energía para grandes conjuntos de datos.
- Evita el trabajo redundante: Usa funciones integradas y optimizadas en el lenguaje de programación o framework que elijas. Estas funciones suelen implementarse en un lenguaje de nivel inferior y más eficiente en cuanto a la energía, como C o C++, por lo que están mejor optimizadas para el hardware subyacente en comparación con las funciones codificadas de forma personalizada.
Selecciona estructuras de datos para la eficiencia
Las estructuras de datos que elijas determinan la velocidad a la que se pueden recuperar, insertar o procesar los datos. Esta velocidad afecta el uso de la CPU y la memoria. Para seleccionar estructuras de datos eficientes, usa los siguientes enfoques:
- Optimiza la búsqueda y la recuperación: Para las operaciones comunes, como verificar si existe un elemento o recuperar un valor específico, prefiere las estructuras de datos que estén optimizadas para la velocidad. Por ejemplo, los mapas hash o los conjuntos hash permiten búsquedas de tiempo casi constante, que es un enfoque más eficiente en cuanto a la energía que la búsqueda lineal en un array.
- Minimiza el espacio en memoria: Las estructuras de datos eficientes ayudan a reducir el espacio en memoria general de una aplicación. La reducción del acceso y la administración de la memoria genera un menor consumo de energía. Además, un perfil de memoria más simple permite que los procesos se ejecuten de manera más eficiente, lo que te permite posponer las actualizaciones de recursos.
- Usa estructuras especializadas: Usa estructuras de datos que estén diseñadas específicamente para un problema determinado. Por ejemplo, usa una estructura de datos de árbol de prefijos para la búsqueda rápida de prefijos de cadenas y usa una cola de prioridad cuando necesites acceder solo al valor más alto o más bajo de manera eficiente.
Optimiza las operaciones de procesamiento y datos
Cuando desarrollas software, enfócate en el uso eficiente y proporcional de los recursos en toda la pila tecnológica. Trata la CPU, la memoria, el disco y la red como recursos limitados y compartidos. Reconoce que el uso eficiente de los recursos genera reducciones tangibles en los costos y el consumo de energía.
Optimiza el uso de la CPU y el tiempo de inactividad
Para minimizar el tiempo que la CPU pasa en un estado activo que consume energía sin realizar un trabajo significativo, usa los siguientes enfoques:
- Prefiere la lógica basada en eventos al sondeo: Reemplaza los bucles ocupados que consumen muchos recursos o la verificación constante (sondeo) por una lógica basada en eventos. Una arquitectura basada en eventos garantiza que los componentes de una aplicación operen solo cuando se activan por eventos relevantes. Este enfoque permite el procesamiento a pedido, lo que elimina la necesidad de un sondeo que consume muchos recursos.
- Evita la alta frecuencia constante: Escribe código que no obligue a la CPU a operar constantemente a su frecuencia más alta. Para minimizar el consumo de energía, los sistemas inactivos deben poder ingresar a estados de baja potencia o modos de suspensión.
- Usa el procesamiento asíncrono: Para evitar que los subprocesos se bloqueen durante los tiempos de espera inactivos, usa el procesamiento asíncrono. Este enfoque libera recursos y genera un mayor uso general de los recursos.
Administra la memoria y la E/S de disco de manera eficiente
El uso ineficiente de la memoria y el disco genera un procesamiento innecesario y un mayor consumo de energía. Para administrar la memoria y la E/S de manera eficiente, usa las siguientes técnicas:
- Administración estricta de la memoria: Toma medidas para liberar de forma proactiva los recursos de memoria sin usar. Evita mantener objetos grandes en la memoria durante períodos más largos de lo necesario. Este enfoque evita los cuellos de botella en el rendimiento y reduce la energía que se consume para el acceso a la memoria.
- Optimiza la E/S de disco: Reduce la frecuencia de las interacciones de lectura y escritura de tu aplicación con los recursos de almacenamiento persistente. Por ejemplo, usa un búfer de memoria intermediario para almacenar datos. Escribe los datos en el almacenamiento persistente en intervalos fijos o cuando el búfer alcance un tamaño determinado.
- Operaciones por lotes: Consolida las operaciones de disco pequeñas y frecuentes en menos operaciones por lotes más grandes. Una operación por lotes consume menos energía que muchas transacciones pequeñas individuales.
- Usa la compresión: Reduce la cantidad de datos que se escriben en los discos o se leen de ellos aplicando técnicas de compresión de datos adecuadas. Por ejemplo, para comprimir los datos que almacenas en Cloud Storage, puedes usar la transcodificación descompresiva.
Minimiza el tráfico de red
Los recursos de red consumen una cantidad significativa de energía durante las operaciones de transferencia de datos. Para optimizar la comunicación de red, usa las siguientes técnicas:
- Minimiza el tamaño de la carga útil: Diseña tus APIs y aplicaciones para transferir solo los datos necesarios para una solicitud. Evita recuperar o devolver estructuras JSON o XML grandes en los casos en que solo se requieran algunos campos. Asegúrate de que las estructuras de datos que se devuelvan sean concisas.
- Reduce los viajes de ida y vuelta: Para reducir la cantidad de viajes de ida y vuelta de la red que se requieren para completar una acción del usuario, usa protocolos más inteligentes. Por ejemplo, prefiere HTTP/3 a HTTP/1.1, elige GraphQL en lugar de REST, usa protocolos binarios y consolida las llamadas a la API. Cuando reduces el volumen de llamadas de red, reduces el consumo de energía de tus servidores y de los dispositivos del usuario final.
Implementa la optimización del frontend
La optimización del frontend minimiza los datos que deben descargar y procesar los usuarios finales, lo que ayuda a reducir la carga en los recursos de los dispositivos del usuario final.
Minimiza el código y los recursos
Cuando los usuarios finales necesitan descargar y procesar recursos más pequeños y estructurados de manera más eficiente, sus dispositivos consumen menos energía. Para minimizar el volumen de descarga y la carga de procesamiento en los dispositivos del usuario final, usa las siguientes técnicas:
- Minimización y compresión: Para los archivos JavaScript, CSS y HTML, quita los caracteres innecesarios, como los espacios en blanco y los comentarios, con las herramientas de minimización adecuadas. Asegúrate de que los archivos, como las imágenes, estén comprimidos y optimizados. Puedes automatizar la minimización y la compresión de los recursos web con una canalización de CI/CD.
- Carga diferida: Carga imágenes, videos y recursos no críticos solo cuando sean necesarios, por ejemplo, cuando estos elementos se desplazan hacia la ventana gráfica de una página web. Este enfoque reduce el volumen de transferencia de datos inicial y la carga de procesamiento en los dispositivos del usuario final.
- Paquetes de JavaScript más pequeños: Elimina el código sin usar de tus paquetes de JavaScript con agrupadores de módulos modernos y técnicas como la eliminación de código no utilizado. Este enfoque genera archivos más pequeños que se cargan más rápido y usan menos recursos del servidor.
- Almacenamiento en caché del navegador: Usa encabezados de almacenamiento en caché HTTP para indicarle al navegador del usuario que almacene recursos estáticos de forma local. El almacenamiento en caché del navegador ayuda a evitar descargas repetidas y tráfico de red innecesario en visitas posteriores.
Prioriza la experiencia del usuario básico (UX)
El diseño de tu interfaz de usuario puede tener un impacto significativo en la complejidad computacional para renderizar el contenido del frontend. Para compilar interfaces de frontend que proporcionen una UX ligera, usa las siguientes técnicas:
- Renderización eficiente: Evita la manipulación frecuente y que consume muchos recursos del Modelo de objetos del documento (DOM). Escribe código que minimice la complejidad de la renderización y elimine la renderización innecesaria.
- Patrones de diseño ligeros: Cuando corresponda, prefiere los sitios estáticos o las apps web progresivas (PWA). Esos sitios y apps se cargan más rápido y requieren menos recursos del servidor.
- Accesibilidad y rendimiento: Los sitios responsivos y de carga rápida suelen ser más sostenibles y accesibles. Un diseño optimizado y sin sobrecarga reduce los recursos que se consumen cuando se renderiza el contenido. Los sitios web optimizados para el rendimiento y la velocidad pueden ayudar a generar mayores ingresos. Según un estudio de investigación de Deloitte y Google, Milliseconds Make Millions, una mejora de 0.1 segundos (100 ms) en la velocidad del sitio genera un aumento del 8.4% en las conversiones para los sitios de venta minorista y un aumento del 9.2% en el valor promedio del pedido.