avatarJason M. Pittman

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

5160

Abstract

">range</span>(n))

<span class="hljs-keyword">def</span> <span class="hljs-title function_">sum_n_squared</span>(<span class="hljs-params">n</span>): total = <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n): <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n): total += i + j <span class="hljs-keyword">return</span> total

n = <span class="hljs-number">1000</span> cProfile.run(<span class="hljs-string">'sum_n({})'</span>.<span class="hljs-built_in">format</span>(n)) cProfile.run(<span class="hljs-string">'sum_n_squared({})'</span>.<span class="hljs-built_in">format</span>(n))</pre></div><p id="40af">The output of the profiler will show that <code>sum_n_squared(n)</code> takes significantly more time than <code>sum_n(n)</code>, as expected from their time complexities (O(n) vs O(n²)).</p><p id="c3b9">Now, this is a simple demonstration. In real applications, the functions would be more complex. Use the profiling results to highlight code ripe for optimization. Pay attention to the code constructs I mentioned <a href="https://readmedium.com/the-fourth-pillar-of-cybersecurity-unveiling-the-essential-role-of-sustainability-in-cyber-defense-922100903795">previously</a>.</p><p id="6519">2. <b>Efficiency Testing</b>: As part of your unit testing, you could include tests that measure the efficiency of your code. This could involve timing how long certain functions take to run or measuring their memory usage. By making efficiency a key part of your testing, you can ensure your code is not only correct but also optimized for green computing. You can use Python’s built-in <code>timeit</code> module to measure execution time and <code>memory_profiler</code> for memory usage.</p><p id="a3bf">We can use Python’s built-in <code>timeit</code> module to test the efficiency of our <code>sum_n</code> and <code>sum_n_squared</code> functions. This module allows us to measure the execution time of small bits of Python code, which can be a good proxy for their energy efficiency (since longer execution times often mean more CPU usage and therefore more energy consumption). The <code>memory_profiler</code> module in Python provides a way to monitor memory usage of a program. Note that the <code>memory_profiler</code> library is not a part of Python's standard library and you will need to install it separately using pip:</p><div id="7514"><pre>pip install memory-profiler</pre></div><p id="2793">Here’s an example of how you can use <code>memory_profiler</code> along with <code>timeit</code> to evaluate the efficiency of <code>sum_n</code> and <code>sum_n_squared</code>:</p><div id="dbe9"><pre><span class="hljs-keyword">import</span> timeit <span class="hljs-keyword">from</span> memory_profiler <span class="hljs-keyword">import</span> memory_usage

<span class="hljs-keyword">def</span> <span class="hljs-title function_">sum_n</span>(<span class="hljs-params">n</span>): <span class="hljs-keyword">return</span> <span class="hljs-built_in">sum</span>(<span class="hljs-built_in">range</span>(n))

<span class="hljs-keyword">def</span> <span class="hljs-title function_">sum_n_squared</span>(<span class="hljs-params">n</span>): total = <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n): <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n): total += i + j <span class="hljs-keyword">return</span> total

n = <span class="hljs-number">1000</span>

<span class="hljs-comment"># Memory and Time evaluation for sum_n</span> mem_usage_before = memory_usage(max_usage=<span class="hljs-literal">True</span>) start_time = timeit.default_timer() sum_n(n) end_time = timeit.default_timer() mem_usage_after = memory_usage(max_usage=<span class="hljs-literal">True</span>)

<span class="hljs-built_in">print</span>(<span class="hljs-string">f"Memory consumed by sum_n: <span class="hljs-subst">{mem_usage_after - mem_usage_before}</span> MiB"</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Time taken by sum_n: <span class="hljs-subst">{end_time - start_time}</span> seconds"</span>)

<span class="hljs-comment"># Memory and Time evaluation for sum_n_squared</span> mem_usage_before = memory_usage(max_usage=<span class="hljs-literal">True</span>) start_time = timeit.default_timer() sum_n_squared(n) end_time = timeit.default_timer() mem_usage_after = memory_usage(max_usage=<span class="hljs-literal">True</span>)

<span class="hljs-built_in">print</span>(<span class="hljs-string">f"Memory consumed by sum_n_squared: <span class="hljs-subst">{mem_usage_after - mem_usage_before}</span> MiB"</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Time taken by sum_n_squared: <span class="hljs-subst">{end_time - start_time}</span> seconds"</span>)</pre></div><p id="feff">In

Options

this code, <code>memory_usage(max_usage=True)</code> is used to measure the maximum memory usage of your Python program. We measure the memory usage before and after calling our functions and then calculate the difference to determine how much additional memory was used by each function.</p><p id="4e59">You should see that <code>sum_n_squared(n)</code> uses more memory and takes more time than <code>sum_n(n)</code>, which is expected given their time complexities.</p><p id="e032">3. <b>Code Reviews for Efficiency</b>: Code reviews are a common practice in software development where other developers review your code to catch bugs and suggest improvements. You can include efficiency and green computing considerations as part of these reviews. For example, reviewers could look for inefficient algorithms that could be replaced with more efficient ones, or unnecessary computations that could be eliminated. This encourages developers to write more efficient code and makes energy efficiency a part of the conversation from the very beginning of the development process.</p><p id="3dc3">We can use the <code>big-O</code>package to aid the code review. This becomes handy when we’re not certain of the Time and Space complexity of a function.</p><p id="9ebc">Let’s consider the same two functions sum_n and sum_n_squared that we used in the previous example. After using cProfile to identify that sum_n_squared is a potential bottleneck, you might suspect that it’s because sum_n_squared has a time complexity of O(n²). You can use the <code>big-O package </code>to confirm this suspicion.</p><div id="47bc"><pre><span class="hljs-keyword">from</span> bigO <span class="hljs-keyword">import</span> BigO <span class="hljs-keyword">from</span> bigO <span class="hljs-keyword">import</span> complexities

<span class="hljs-keyword">def</span> <span class="hljs-title function_">sum_n</span>(<span class="hljs-params">n</span>): <span class="hljs-keyword">return</span> <span class="hljs-built_in">sum</span>(<span class="hljs-built_in">range</span>(n))

<span class="hljs-keyword">def</span> <span class="hljs-title function_">sum_n_squared</span>(<span class="hljs-params">n</span>): total = <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n): <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n): total += i + j <span class="hljs-keyword">return</span> total

<span class="hljs-comment"># Create an instance of BigO</span> my_O = BigO()

<span class="hljs-comment"># Generate time complexity graph for sum_n</span> positive_int_generator = <span class="hljs-keyword">lambda</span> n: n <span class="hljs-comment"># generator of input</span> my_O.time_complexity(sum_n, positive_int_generator, min_n=<span class="hljs-number">10</span>, max_n=<span class="hljs-number">1000</span>, n_measures=<span class="hljs-number">100</span>, n_repeats=<span class="hljs-number">3</span>, verbose=<span class="hljs-literal">False</span>, complexity=complexities.linear)

<span class="hljs-comment"># Generate time complexity graph for sum_n_squared</span> my_O.time_complexity(sum_n_squared, positive_int_generator, min_n=<span class="hljs-number">10</span>, max_n=<span class="hljs-number">300</span>, n_measures=<span class="hljs-number">100</span>, n_repeats=<span class="hljs-number">3</span>, verbose=<span class="hljs-literal">False</span>, complexity=complexities.quadratic)</pre></div><p id="0ec8">This will generate two graphs, one for each function, that plot the execution time against the size of the input. The graphs will show that <code>sum_n</code> has a time complexity of O(n), and <code>sum_n_squared</code> has a time complexity of O(n^2), which aligns with our expectations.</p><p id="e3e6">Please note that the <code>big-O</code> library is not part of the Python standard library and would need to be installed separately using pip:</p><div id="9288"><pre>pip install big-O</pre></div><p id="38c5">It’s worth mentioning that generating the complexity graphs can take some time. While linear functions are quick, quadratic function with larger inputs can take much longer. This is, of course, due to the nature of the computations involved.</p><p id="5999">These three green computing evaluations can help make your Python code more energy-efficient. However, it’s important to remember that green computing involves more than just optimizing code — it also involves considerations like using energy-efficient hardware, minimizing electronic waste, and using renewable energy sources.</p><p id="f34a">Most importantly, green computing is a responsibility we all share. Every function we optimize makes a difference. So, get to it and happy coding!</p><p id="10e0">If you appreciate this story, here are three actions you can take right now to support my work:</p><ol><li>Give the story a CLAP 👏</li><li>FOLLOW me to get notified of new stories ⏰</li><li>SHARE and recommend this story on your social media 🐦</li></ol></article></body>

Top 3 Ways to Implement Green Computing Evaluations in Python Unit Testing

Photo by Lukasz Szmigiel on Unsplash

Green computing is not just a theoretical concept. We can apply it as a practical solution. I say it is critical we do so today. I recognize work is underway with energy-efficient hardware. Amazon and Microsoft are making great strides in making cloud sustainable. My interest lies elsewhere.

Not all of us can participate in hardware engineering. Few of us can do something about how cloud services operate beneath our tenant spaces. However, all of us can optimize the software we develop. An easy way to do so is through unit testing. I’m going to reveal the top 3 ways to implement green computing evaluations into our Python tests.

The Importance of Green Computing

By incorporating green computing practices into unit testing, we can ensure that our code is not only functionally correct, but also energy-efficient and environmentally friendly. It’s a way of baking sustainability right into the core of our software development practices.

Incorporating green compute evaluations in unit testing is important for several reasons:

1. Environmental Impact: The energy used by computers contributes to greenhouse gas emissions, especially when that energy comes from non-renewable sources. By making our code more energy-efficient, we can reduce its environmental impact.

2. Performance: Code that’s more energy-efficient often performs better, as it’s usually doing less unnecessary work. This can lead to faster execution times and a better user experience.

3. Cost Savings: More energy-efficient code can also lead to cost savings, especially in large-scale or cloud-based applications. Using less energy means lower electricity bills, and also potentially less money spent on cooling (since computers generate heat when they run).

4. Future-Proofing: As energy costs rise and the world moves towards more sustainable practices, energy-efficient code is likely to become more and more important. By incorporating green compute evaluations into your testing now, you’re preparing for this future.

5. Social Responsibility: As members of society, we all have a role to play in protecting our environment. By making our code more energy-efficient, we’re doing our part to reduce greenhouse gas emissions and combat climate change.

Implementing Green Computing Evaluations

When it comes to implementing green computing evaluations in Python unit testing, the focus should be on identifying the sections of code that consume the most energy and optimizing them. Here are three ways to do that:

1. Profiling: Profiling is a process that helps you understand where your program spends its time. It also shows which function calls are the costliest. In the context of green computing, you can use profiling to identify parts of your code that use the most CPU resources. Python has several built-in and third-party profiling tools, such as cProfile, profile, or line_profiler. Once you've identified resource-heavy parts of your code, you can focus on optimizing them to reduce energy consumption.

Let’s consider two functions. One is linear time complexity O(n) function which simply sums the numbers up to n, and the other is a quadratic time complexity O(n²) function which computes the sum of an outer and inner loop.

def sum_n(n):
    return sum(range(n))

def sum_n_squared(n):
    total = 0
    for i in range(n):
        for j in range(n):
            total += i + j
    return total

Now we can use cProfile to profile these functions:

import cProfile

def sum_n(n):
    return sum(range(n))

def sum_n_squared(n):
    total = 0
    for i in range(n):
        for j in range(n):
            total += i + j
    return total

n = 1000
cProfile.run('sum_n({})'.format(n))
cProfile.run('sum_n_squared({})'.format(n))

The output of the profiler will show that sum_n_squared(n) takes significantly more time than sum_n(n), as expected from their time complexities (O(n) vs O(n²)).

Now, this is a simple demonstration. In real applications, the functions would be more complex. Use the profiling results to highlight code ripe for optimization. Pay attention to the code constructs I mentioned previously.

2. Efficiency Testing: As part of your unit testing, you could include tests that measure the efficiency of your code. This could involve timing how long certain functions take to run or measuring their memory usage. By making efficiency a key part of your testing, you can ensure your code is not only correct but also optimized for green computing. You can use Python’s built-in timeit module to measure execution time and memory_profiler for memory usage.

We can use Python’s built-in timeit module to test the efficiency of our sum_n and sum_n_squared functions. This module allows us to measure the execution time of small bits of Python code, which can be a good proxy for their energy efficiency (since longer execution times often mean more CPU usage and therefore more energy consumption). The memory_profiler module in Python provides a way to monitor memory usage of a program. Note that the memory_profiler library is not a part of Python's standard library and you will need to install it separately using pip:

pip install memory-profiler

Here’s an example of how you can use memory_profiler along with timeit to evaluate the efficiency of sum_n and sum_n_squared:

import timeit
from memory_profiler import memory_usage

def sum_n(n):
    return sum(range(n))

def sum_n_squared(n):
    total = 0
    for i in range(n):
        for j in range(n):
            total += i + j
    return total

n = 1000

# Memory and Time evaluation for sum_n
mem_usage_before = memory_usage(max_usage=True)
start_time = timeit.default_timer()
sum_n(n)
end_time = timeit.default_timer()
mem_usage_after = memory_usage(max_usage=True)

print(f"Memory consumed by sum_n: {mem_usage_after - mem_usage_before} MiB")
print(f"Time taken by sum_n: {end_time - start_time} seconds")

# Memory and Time evaluation for sum_n_squared
mem_usage_before = memory_usage(max_usage=True)
start_time = timeit.default_timer()
sum_n_squared(n)
end_time = timeit.default_timer()
mem_usage_after = memory_usage(max_usage=True)

print(f"Memory consumed by sum_n_squared: {mem_usage_after - mem_usage_before} MiB")
print(f"Time taken by sum_n_squared: {end_time - start_time} seconds")

In this code, memory_usage(max_usage=True) is used to measure the maximum memory usage of your Python program. We measure the memory usage before and after calling our functions and then calculate the difference to determine how much additional memory was used by each function.

You should see that sum_n_squared(n) uses more memory and takes more time than sum_n(n), which is expected given their time complexities.

3. Code Reviews for Efficiency: Code reviews are a common practice in software development where other developers review your code to catch bugs and suggest improvements. You can include efficiency and green computing considerations as part of these reviews. For example, reviewers could look for inefficient algorithms that could be replaced with more efficient ones, or unnecessary computations that could be eliminated. This encourages developers to write more efficient code and makes energy efficiency a part of the conversation from the very beginning of the development process.

We can use the big-Opackage to aid the code review. This becomes handy when we’re not certain of the Time and Space complexity of a function.

Let’s consider the same two functions sum_n and sum_n_squared that we used in the previous example. After using cProfile to identify that sum_n_squared is a potential bottleneck, you might suspect that it’s because sum_n_squared has a time complexity of O(n²). You can use the big-O package to confirm this suspicion.

from bigO import BigO
from bigO import complexities

def sum_n(n):
    return sum(range(n))

def sum_n_squared(n):
    total = 0
    for i in range(n):
        for j in range(n):
            total += i + j
    return total

# Create an instance of BigO
my_O = BigO()

# Generate time complexity graph for sum_n
positive_int_generator = lambda n: n  # generator of input
my_O.time_complexity(sum_n, positive_int_generator, min_n=10, max_n=1000, n_measures=100, n_repeats=3, verbose=False, complexity=complexities.linear)

# Generate time complexity graph for sum_n_squared
my_O.time_complexity(sum_n_squared, positive_int_generator, min_n=10, max_n=300, n_measures=100, n_repeats=3, verbose=False, complexity=complexities.quadratic)

This will generate two graphs, one for each function, that plot the execution time against the size of the input. The graphs will show that sum_n has a time complexity of O(n), and sum_n_squared has a time complexity of O(n^2), which aligns with our expectations.

Please note that the big-O library is not part of the Python standard library and would need to be installed separately using pip:

pip install big-O

It’s worth mentioning that generating the complexity graphs can take some time. While linear functions are quick, quadratic function with larger inputs can take much longer. This is, of course, due to the nature of the computations involved.

These three green computing evaluations can help make your Python code more energy-efficient. However, it’s important to remember that green computing involves more than just optimizing code — it also involves considerations like using energy-efficient hardware, minimizing electronic waste, and using renewable energy sources.

Most importantly, green computing is a responsibility we all share. Every function we optimize makes a difference. So, get to it and happy coding!

If you appreciate this story, here are three actions you can take right now to support my work:

  1. Give the story a CLAP 👏
  2. FOLLOW me to get notified of new stories ⏰
  3. SHARE and recommend this story on your social media 🐦
Green Computing
Sustainability
Computer Science
Python
Unit Testing
Recommended from ReadMedium