Energy-efficient programming with Go and beyond
Greener Coding
Go has a reputation for producing energy-saving applications, but you still have to know what you are doing.
Applications use the processor in different ways, and those differences are sometimes reflected in the power bill. The programming language you choose has a significant influence on energy consumption. But developers still need to go the extra mile to leverage the language's capabilities.
At first glance, Go comes with everything you need for energy efficiency. It has a lean syntax, and smart Goroutines distribute parallel tasks efficiently to the processor cores, thus avoiding a bloated runtime environment that needs to manage complex class hierarchies or juggle classic threads. And the compiler translates the source code into a native and therefore fast program, which means the processor can go back to sleep sooner and save energy. On top of that, Go statically links all external modules into the finished binary, eliminating the administrative overhead of dynamic libraries during execution.
This contrasts strongly with Java, where a compiler converts the program into intermediate code, which is then executed by a virtual machine. This additional software layer slows down execution and costs unnecessary energy. The situation is even worse for interpreted languages: PHP and Python parse each line of code step-by-step during execution. Numerous optimizations and just-in-time compilers are intended to make the resulting applications faster, but there is still some loss, depending on the task. If you want to develop energy-efficient programs, you need to go for Go, right? Or maybe not? The following look at energy efficiency in Go is a useful entry point for examining some more general rules for more efficient coding.
SLE Research
Back in 2017, a team of researchers wanted to know which programming language produces particularly energy-efficient applications. They presented the results of their study at the International Conference on Software Language Engineering (SLE [1]). According to the study, compiling programming languages such as C and Go work far more efficiently than interpreted counterparts such as PHP or Python. The results are less clear for languages that generate intermediate code. Java programs, for example, run faster and in a more energy-efficient way on average than their Go counterparts (Figure 1). Surprisingly, the virtual machine doesn't seem to slow things down – at least not in the trial, which has a few bugs on closer inspection.
The SLE study serves as a wake-up call for those who think they are automatically writing more efficient code just by choosing Go. However, a closer look also points to the complexity of these energy efficiency issues – and the danger of making assumptions based on a single study.
Initially, the researchers used only one possible compiler or interpreter for each language. Another Go compiler named TinyGo harnesses the LLVM framework to create highly optimized machine code for microcontrollers [2]. The C code in the study was compiled exclusively using the GCC.
The Go compiler used was version 1.6, and this was already considered obsolete at the time of the study. Of course, the other compilers and interpreters have also been revised and further optimized in the meantime. For example, PHP 8 can handle significantly more concurrent requests than its predecessors.
No Clouds
The researchers used the Computer Language Benchmark Game (Figure 2) for their measurements. This benchmark [3] consists of 10 individual tests implemented in a total of 28 languages. Among other things, these small programs calculate Mandelbrot sets and binary trees. The study only investigated which languages perform these individual manageable calculations in an energy-efficient manner. In contrast to this, real applications need to solve completely different tasks. Encryption tools, for example, struggle with extremely tricky mathematical problems, whereas web servers merely push data packets across the network.
Complex Internet and cloud applications, such as the ownCloud Infinite Scale (oCIS [4]) file sharing platform implemented in Go, were not included in the tests. OCIS was created as a more powerful alternative to the classic ownCloud PHP application, which reached its limits when faced with higher loads and many simultaneous users. The oCIS developers made their own attempt to optimize oCIS, and in the meantime, they ended up learning a lot about how to optimize Go. Unlike the small benchmark programs, however, oCIS consists of numerous services that work together on a network. The oCIS developers had to take a slightly different approach to their assessment.
If an application solves a task as quickly as possible, the processor can switch back to one of its energy-saving modes faster. It is therefore not surprising that, in the SLE study, the compiler languages were also the most energy-efficient. The oCIS developers also currently assume that high-performance programs consume less energy. This assumption allows for a focus on performance measurements and optimizations for which established tools and processes exist.
Go helps its developers with a built-in profiler [5]. The profiler measures the execution times for code parts to detect inefficient operations. According to Klaas Freitag, CIO of ownCloud GmbH, the Go profiler is usually only suitable for tracking down bugs, especially in distributed systems. This is why the oCIS team used an in-house development for its performance measurements: a tool named cdperf
[6], which in turn harnesses the well-known k6
test tool [7] (Figure 3). The k6
test tool simulates multiple users accessing the file sharing platform simultaneously.
If so desired, the Go compiler can run customized benchmarks that you can use to determine the performance of code changes [8]. For example, if a function calculates the greatest common divisor, you could call a DIY benchmark individually for thousands of different pairs of numbers. If the benchmark delivers a shorter runtime after a code change, you have successfully optimized the task of computing the greatest common divisor. The benchmarks can be maintained along with the (unit) tests and included in the development from the beginning.
Know Your Language
Once you have identified inefficient parts of the program, you need to optimize the source code; more specifically, you need to find the most efficient algorithms. Many programming languages support efficient development by evaluating constructs. For example, the Go compiler can already evaluate constant expressions, which saves computation time later during execution. However, this feature requires the developers to correctly integrate the constant expressions into the source code.
Furthermore, Go is a typed language that distinguishes between floating point and integer numbers. Because many processors calculate faster with integers, you should give them preference if possible. This is especially true if you use them as loop counters. Speaking of loops: Classic brakers and power guzzlers include nested but actually superfluous loops, sprawling recursions, and unnecessary repetitions. If a program has to recalculate all the thumbnails every time the image gallery is called up, for example, this repetitive work eats up energy unnecessarily.
The Go developers provide many more tips for efficient programming [9] on a separate page (Figure 4). Comparable collections exist for other languages. In any case, you should not rush into every single file operation. From Freitag's point of view, such simple operations are already optimized. For example, PHP saves a file to disk just as quickly as a Go program would.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Rhino Linux Announces Latest "Quick Update"
If you prefer your Linux distribution to be of the rolling type, Rhino Linux delivers a beautiful and reliable experience.
-
Plasma Desktop Will Soon Ask for Donations
The next iteration of Plasma has reached the soft feature freeze for the 6.2 version and includes a feature that could be divisive.
-
Linux Market Share Hits New High
For the first time, the Linux market share has reached a new high for desktops, and the trend looks like it will continue.
-
LibreOffice 24.8 Delivers New Features
LibreOffice is often considered the de facto standard office suite for the Linux operating system.
-
Deepin 23 Offers Wayland Support and New AI Tool
Deepin has been considered one of the most beautiful desktop operating systems for a long time and the arrival of version 23 has bolstered that reputation.
-
CachyOS Adds Support for System76's COSMIC Desktop
The August 2024 release of CachyOS includes support for the COSMIC desktop as well as some important bits for video.
-
Linux Foundation Adopts OMI to Foster Ethical LLMs
The Open Model Initiative hopes to create community LLMs that rival proprietary models but avoid restrictive licensing that limits usage.
-
Ubuntu 24.10 to Include the Latest Linux Kernel
Ubuntu users have grown accustomed to their favorite distribution shipping with a kernel that's not quite as up-to-date as other distros but that changes with 24.10.
-
Plasma Desktop 6.1.4 Release Includes Improvements and Bug Fixes
The latest release from the KDE team improves the KWin window and composite managers and plenty of fixes.
-
Manjaro Team Tests Immutable Version of its Arch-Based Distribution
If you're a fan of immutable operating systems, you'll be thrilled to know that the Manjaro team is working on an immutable spin that is now available for testing.