Hello. My name is Stas, at Domclick I oversee the development of back office services for mortgage lending at Sberbank.
Recently, in all sorts of reports and podcasts, I have often come across the term "Green Code". Having rummaged on the Internet and studied this topic, I realized that this term describes a set of techniques in the development and design of applications that can reduce the power consumption of the equipment on which this code is executed.
More or less this question is usually puzzled by developers of mobile applications, mainly because the device on which their code will be executed has a limited battery capacity.
The topic has become quite "hype", and I decided to figure out how exactly the principles of "green" can be reflected in WEB-development.
Basic principles of writing "green code"
After reading a lot of reports and articles on this topic, I would highlight the following aspects of application development that affect power consumption:
1) Simplification and optimization of algorithms
As mentioned above, the execution of the code should lead to minimal energy consumption. The optimized code will run faster and, therefore, will require less processing and equipment cooling costs.
Let's try to calculate the difference in energy consumption for executing a specific operation in the code - the classic sorting of a list. I will deliberately exaggerate the situation in the given example to show the difference in more contrast.
Let's take a bubble sort. This is probably one of the most sub-optimal ways. Very suitable for us. Let's calculate the sorting of the list and see how it affected the power consumption of the MacBook. First, let's simulate the data array and the bubble sort logic itself:
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)
To measure the impact of code execution on energy consumption, I used the iStat Menus 6 monitoring system (https://bjango.com/mac/istatmenus/). I connected my MacBook to the network, closed all third-party applications, waited for a certain time to charge the battery, and started sorting: Power consumption
graph when performing bubble sort: You can
see a pronounced jump in power consumption lasting 305 seconds. It was caused by the execution of our non-optimal request. Additionally, the energy spent for 5 minutes (305 seconds)
P = (W2 – W1) × 305 = (17,29 [ ] – 2,9 [ ]) × 305 = 14,39 × 305 = 4389 = 0,0012 *
.
Now let's say that this code accidentally got to an industrial product server (let's assume that the additional power consumption on the server will be the same as on my MacBook, and the dependence is directly proportional) and began to be executed with a frequency of 1 every 10 seconds. Then a year we get more energy:
365 × 24 × 3600 /10 × 0,0012 * = 3 784,32 *
.
Suppose that the data center hosting the server receives power from a boiler room that uses birch wood as fuel. When burning 1 m 3 of birch wood, 1900 kW * h / m 3 of energy is released. Of course, the efficiency of the boiler is not 100%, and if we take it for 75%, we get: . If we take a tree as a regular cylinder, the volume of which is
(3 784,32 / 1900) / 0,75 = 2,66 3
V = Pi × R2 × H
where R is the radius of the tree trunk, let's take it as 0.12 meters (average value),
H is the height of the tree trunk, let's take it as 3 meters (average value).
then we get: This means that there will be wood in one cubic meter . We need a year to power our script . For comparison, I performed the same sort using the standard Python sorting method ( ). Energy consumption graph when performing standard sorting in Python: Applying the same calculation logic (the peak duration was 10 seconds), we get: In a year we get (provided that the operation is performed 1 time in 10 seconds) Or:
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 .
Of course, this example has a lot of assumptions, and bubble sort is rarely done. But the resulting numbers seemed interesting to me
2) Use the event driven model of the application wherever possible
The point is that most processors support multiple "states" of power consumption. In the event that the kernel is not busy with any calculations, the operating system puts it into a “sleep” state, in which the processor consumes much less power.
Spectrum of states (energy optimization):
You can read more about this here .
Quite often, there is a situation where some application logic must be executed when a certain event occurs. And to find out that this event has occurred, the service interested in receiving this information often periodically polls the service that stores the fact that this event has been completed. By timer. Moreover, the overwhelming majority of requests receive a negative answer, that is, 99% of requests, in fact, are not needed.
It would be correct to broadcast the corresponding event to the queue and read the fact of its occurrence to all interested services.
Spectrum of states (energy optimization):
Another example is the interaction of front-end and back-end application components. If the front needs to change its state depending on the data in the database, sometimes requests are periodically sent to the backend, creating unnecessary additional load. Although it is possible to inform the front about a change in the state of the necessary data through the socket server.
While sockets can be mistaken as well, here's an example of "bad" code:
while(true)
{
// Read data
result = recv(serverSocket, buffer, bufferLen, 0);
// Handle data
if(result != 0)
{
HandleData(buffer);
}
// Sleep and repeat
Sleep(1000);
}
It can be seen that even if no data arrived at the socket, the code will still be executed every 1000 seconds, wasting precious energy.
The same thing can be written in a slightly different way, and less energy will be spent:
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: «»
If the data is still used, but rarely, then it is better not to display it by default, but to show it only by clicking the "Show detailed information" button.
A simple example illustrating this principle: displaying lists of data objects (requests, users, outlets, warehouses, offices), provided that the scenario for using the form still involves finding the desired object.
An example of a bad interface :
The page displays a huge list of tasks (divided into "pages"), but the user will still search for a specific client (according to some logic in his head) in the search bar at the top. Why waste resources getting a to-do list?
The same scenario, implemented in a different way:
Example of a "green" interface :
The client selection logic has been moved to the system; by default, unnecessary data is not requested "out of habit". This option, in addition to environmentalists, and cybersecurity will be fiercely applauded.
4) Refactoring
Refactoring is almost always useful. But in this context, it is needed for one simple purpose: to throw out unnecessary (garbage) code or to simplify the existing one to reduce power consumption.
Many applications that have been developing for more than three years accumulate hundreds of lines of unused or unpredictably working code left over from previously implemented (and possibly already cut) functions. Sometimes this code is even executed, but the result of its work is not required.
Periodic auditing and refactoring will reduce the amount of such code, although it probably won't get rid of it completely.
For example, while regularly refactoring one of our services (within the technical quota of working hours), we found this:
Example of refactoring :
crm_deal_id
- identifier of the mortgage transaction in the old system. Now it is no longer needed, but the code is still checking to get it and calling an additional function delete_deal_chat_telephony
that performs a lot of other actions.
All of this can be removed without losing functionality.
5) Use low-level programming languages for high-load applications
Obviously, in most cases, applications written in low-level languages are more energy efficient. It makes sense to rewrite a loaded service in Python (if it performs a simple operation) in C / C +. It will be faster and greener.
True, often we do not have the necessary knowledge to write logic in such languages.
6) Group I / O operations
Storage systems, like processors, also have different power states.
In "sleep" mode, much less energy is consumed than in an operating "warm" state. This is especially true for storage systems / hard drives.
If the application can group the data written to the disk and access the disk not constantly, but at certain periods of time, then this will be more energy efficient, since during the period of “idle” the operating system will send the disk to “hibernation”.
7) Using less power-hungry storage systems for logs
It is good practice to use "hot" and "cold" storage. For example, it makes sense to store logs for the last week in the indexed form of "hot" cooking, since the probability of accessing them will be quite high. Longer logs can be stored in cheaper and less power-hungry storage systems.
How about on an industrial scale?
Above, we covered the basic techniques for working with code to ensure its energy efficiency. But even following most of these rules will yield very modest savings that will be difficult to visualize. Of course, if the lists are not sorted by the bubble method in sales, the
purposeful development of functionality for the implementation of electronic document management will give a much greater effect.
One of the activities of the Domclick teams is to optimize and simplify the process of obtaining a mortgage. And in this mortgage process, at the final stage, a lot of documents are prepared on paper. And in several copies. One copy for the seller, one for the buyer, one for the bank file.
I am pleased to know that Domclick is spending a lot of effort to eliminate this vicious practice and to transfer the entire document flow to electronic format. This year, a significant part of mortgage transactions has already been fully digitized (only one paper was printed: an application for the issuance of a UKEP, an enhanced cryptographic electronic signature). All other documents were signed by this UKEP and no paper was spent on them.
This initiative has already saved over 67,491,108 sheets of paper. In birches, there are about 23,000 trees!
Protect the environment!
Links for those interested:
- Green IT - available data and guidelines for reducing energy consumption in IT Systems / Ardito L .; Morisio M… - In: SUSTAINABLE COMPUTING. - 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