Русский
Русский
English
Статистика
Реклама

Greencode

Green Code и березки. Основные принципы зеленого кода в разработке

08.09.2020 12:21:09 | Автор: admin


Всем привет. Меня зовут Стас, в компании Домклик я курирую разработку сервисов бек-офиса для ипотечного кредитования Сбербанка.

В последнее время во всевозможных докладах и подкастах я довольно часто стал встречать термин Green Code. Покопавшись в интернете и изучив эту тему, стало понятно, что этим термином описывают комплекс приёмов в разработке и проектировании приложений, позволяющих сократить энергопотребление оборудования, на котором этот код выполняется.

Более-менее этим вопросом обычно озадачиваются разработчики мобильных приложений, в основном потому, что устройство, на котором будет выполняться их код, имеет ограниченную емкость батареи.

Тема стала достаточно хайповой, и я решил прикинуть, как именно принципы зеленого могут быть отражены в WEB-разработке.

Основные принципы написания зеленого кода


Прочитав достаточно много докладов и статей на эту тему, я бы выделил следующие аспекты разработки приложений, которые влияют на энергопотребление:

1) Упрощение и оптимизация алгоритмов


Как уже было сказано выше, выполнение кода должно приводить к минимальному потреблению энергии. Оптимизированный код будет выполняться быстрее и, соответственно, потребует меньше затрат на его обработку и охлаждение оборудования.

Давайте попробуем посчитать разницу в энергозатратах на исполнение конкретной операции в коде классической сортировке списка. Я специально буду утрировать ситуацию в приведенном примере, чтобы контрастнее показать разницу.

Возьмём сортировку методом пузырька. Наверное, это один из самых неоптимальных способов. Очень нам подходит. Рассчитаем сортировку списка и посмотрим, как она отразилась на энергозатратах MacBook. Для начала смоделируем массив данных и саму логику сортировки пузырьком:

from random import randintdef 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] = buffproductNumber = 60000products = []for i in range(productNumber):    products.append(randint(1, 1000))bubble(products)print(products)

Для замера влияния исполнения кода на энергозатраты я использовал систему мониторинга iStat Menus 6 (http://personeltest.ru/aways/bjango.com/mac/istatmenus/). Подключил MacBook к сети, закрыл все сторонние приложения, выждал определенное время для зарядки батареи, и запустил сортировку:

График энергопотребления при выполнении сортировки пузырьком:



Виден ярко выраженный скачок потребления мощности длительностью в 305 секунд. Он вызван исполнением нашего неоптимального запроса. Дополнительно потраченная энергия за 5 минут (305 секунд):

P = (W2 W1) 305 = (17,29 [мощность при выполнении скрипта] 2,9 [мощность в состоянии покоя]) 305 = 14,39 305 = 4389 Дж = 0,0012 кВт*ч .

Теперь допустим, что этот код случайно попал на промышленный продуктовый сервер (примем как допущение, что дополнительные энергозатраты на сервере будут такими же, как на моем MacBook, и зависимость прямо пропорциональная) и стал выполняться с частотой 1 раз в 10 секунд. Тогда в год мы получим дополнительные энергозатраты:

365 дней 24 часа 3600 с/10 0,0012 кВт*ч = 3 784,32 кВт*ч.

Предположим, что ЦОД, в котором размещается сервер, получает энергоснабжение от котельной, в качестве топлива в которой используется березовая древесина. При сгорании 1 м3 березовой древесины выделяется 1900 кВт*ч/м3 энергии. Разумеется, КПД котельной не 100 %, и если принять его за 75 %, то получим:

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

Если принять дерево за правильный цилиндр, объем которого равен

V = Pi R2 H

где R радиус ствола дерева, примем его за 0,12 метра (среднее значение),
H высота ствола дерева, примем ее за 3 метра (среднее значение).

то получаем:

V = 3,14 0,0144 3 = 0,14 м3

Значит, в одном кубометре древесины будет 1 / 0,14 = 7,14 бревна.

Для обеспечения энергией работы нашего скрипта нам понадобится в год 2,66 м3 7,14 = 19 берез.

Для сравнения я выполнил ту же сортировку с использованием стандартного способа сортировки в Python (.sort()).

График энергопотребления при выполнении стандартной сортировки в Python:



Применяя ту же логику расчета (длительность пика была 10 сек), получаем:

P = (W2 W1) 10 сек = (3,51 [мощность при выполнении скрипта] 2,9 [мощность в состоянии покоя]) 10 сек = 6,1 Дж = 0,0000016 кВт*ч

В год получим (при условии выполнения операции 1 раз в 10 секунд)

365 дней 24 часа 3600 с/10 0,0000016 кВт*ч = 5,05 кВт*ч

Или же:

5,05 / 1900 / 0,75 7,14 = 0,025 бревна березы.

Конечно, в этом примере много допущений, да и сортировку пузырьком делают достаточно редко. Но полученные числа показались мне интересными

2) Использовать событийную модель (event driven model) работы приложения там, где только можно

.
Дело в том, что большинство процессоров поддерживают несколько состояний энергопотребления. В том случае, если ядро не занято какими-то вычислениями, операционная система переводит его в состояние сна, при котором процессор потребляет гораздо меньше энергии.

Спектр состояний (оптимизация по энергопотреблению):



Подробнее об этом можно прочитать тут.

Довольно часто бывает ситуация, когда какая-то логика приложения должна выполниться при возникновении определенного события. И чтобы узнать, что это событие произошло, заинтересованный в получении этой информации сервис зачастую периодически опрашивает сервис, хранящий факт выполнения этого события. По таймеру. Причем подавляющая часть запросов получает отрицательный ответ, то есть 99 % запросов, по сути, не нужны.

Правильно было бы транслировать соответствующее событие в очередь, и считывать факт его возникновения всем заинтересованным сервисам.

Спектр состояний (оптимизация по энергопотреблению):


Другой пример взаимодействие фронтенд- и бекенд-компонентов приложения. Если фронту надо поменять свое состояние в зависимости от данных в базе, иногда на бекенд периодически шлют запросы, создавая ненужную дополнительную нагрузку. Хотя можно проинформировать фронт об изменении состояния необходимых данных через сокетсервер.

Хотя с сокетами тоже можно ошибиться, вот пример плохого кода:

while(true){        // Read data        result = recv(serverSocket, buffer, bufferLen, 0);        // Handle data          if(result != 0)        {                HandleData(buffer);        }        // Sleep and repeat        Sleep(1000);}

Видно, что даже если данные в сокет не поступили, всё равно каждые 1000 секунд код будет выполняться, тратя драгоценную энергию.

То же самое можно написать чуть по-другому, и энергии будет тратиться меньше:

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: Интерфейс пользователя не должен показывать лишние данные


Если данные всё же используются, но редко, то лучше их не отображать по умолчанию, а показывать только по кнопке Показать детальную информацию.

Простой пример, иллюстрирующий этот принцип: отображение списков объектов данных (заявок, пользователей, торговых точек, складов, офисов) при условии, что сценарий использования формы всё равно предполагает поиск нужного объекта.

Пример плохого интерфейса:



На странице отображается огромный список задач (разбитый на страницы), однако пользователь всё равно будет искать определенного клиента (по определенной логике у него в голове) в поисковой строке сверху. Зачем тратить ресурсы на получение списка задач?

Тот же самый сценарий, реализованный по-другому:

Пример зеленого интерфейса:



Логика выбора клиента перенесена в систему, по умолчанию не запрашивается лишних данных по привычке. Этому варианту, помимо экологов, и кибербезопасность будет люто аплодировать.

4) Рефакторинг


Рефакторинг полезен почти всегда. Но в этом контексте он нужен для одной простой цели: выкинуть ненужный (мусорный) код или упростить существующий, чтобы снизить энергопотребление.

Многие приложения, развивающиеся более трёх лет, накапливают в себе сотни строк неиспользуемого или непрогнозируемо работающего кода, оставшегося от ранее реализованных (и уже, возможно, выпиленных) функций. Иногда этот код даже исполняется, но результат его работы не востребован.

Периодический аудит и рефакторинг снизят количество такого кода, хотя, вероятно, избавиться от него до конца не получится.

К примеру, регулярно рефакторя один из наших сервисов (в рамках технической квоты рабочего времени), мы обнаружили вот такое:

Пример рефакторинга:



crm_deal_id идентификатор ипотечной сделки в старой системе. Сейчас он уже не нужен, но в коде осталась проверка на его получение и вызов дополнительной функции delete_deal_chat_telephony, которая выполняет еще кучу действий.

Всё это можно убрать без потери функциональности.

5) Использовать низкоуровневые языки программирования для высоконагруженных приложений


Очевидно, что в большинстве случаев приложения, написанные на низкоуровневых языках, более энергоэффективны. Нагруженный сервис на Python (если он выполняет простую операцию) имеет смысл переписать на C/C+. Будет быстрее и зеленее.

Правда, часто у нас нет нужных знаний для написания логики на таких языках.

6) Группировать I/O-операции


Системы хранения, как и процессоры, также имеют различные состояния энергопотребления.
В режиме сна потребляется гораздо меньше энергии, чем в рабочем прогретом состоянии. Особенно это характерно для систем хранения/жестких дисков.

Если в работе приложения можно группировать данные, записываемые на диск, и обращаться к диску не постоянно, а в определенные периоды времени, то это будет энергоэффективнее, поскольку в период простоя операционная система отправит диск в спячку.

7) Использование менее энергоемких систем хранения для логов


Хорошей практикой будет использовать горячее и холодное хранение. Например, логи за последнюю неделю имеет смысл хранить в индексированном виде горячего приготовления, поскольку вероятность обращения к ним будет достаточно высока. Логи за более длительный период можно хранить в более дешевых и менее энергозатратных системах хранения.

А как в промышленном масштабе?


Выше мы рассмотрели основные приемы работы с кодом для обеспечения его энергоэффективности. Но даже соблюдение большинства этих правил даст весьма скромную экономию, которую сложно будет визуализировать. Конечно, если в проде не сортировать списки методом пузырька

Гораздо больший эффект даст целенаправленная разработка функциональности по внедрению электронного документооборота.

Одним из направлений деятельности команд Домклик является оптимизация и упрощение процесса получения ипотеки. И в этом ипотечном процессе на финальной стадии готовится достаточно много документов на бумаге. Причем в нескольких экземплярах. Один экземпляр для продавца, один для покупателя, один для архива банка.

Мне приятно осознавать, что Домклик тратит много усилий для изничтожения этой порочной практики и перевода всего документооборота в электронный формат. В этом году значительная часть ипотечных сделок была уже полностью оцифрована (печаталась только одна бумага: заявление на выпуск УКЭП, усиленной криптографической электронной подписи). Все остальные документы подписывались уже этим УКЭП и бумага на них не тратилось.

Благодаря этой инициативе было сэкономлено уже более 67 491 108 листов бумаги. В березках это примерно 23 000 деревьев!

Берегите природу!

Ссылки для интересующихся:
  1. Green IT available data and guidelines for reducing energy consumption in IT Systems / Ardito L.; Morisio M In: SUSTAINABLE COMPUTING. 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
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru