diff --git a/CHANGELOG.md b/CHANGELOG.md index 366aab86..a1837ddf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Added rule GCI620 : Avoid invariant computations in loops ### Changed diff --git a/RULES.md b/RULES.md index 5bf43932..b66d1af4 100644 --- a/RULES.md +++ b/RULES.md @@ -82,7 +82,9 @@ Some are applicable for different technologies. | | Non-outsourced CSS and Javascript | If you include CSS or JavaScript code in the body of the HTML file, while the HTML file is used by several pages (or even the entire site), this code must be transferred for each page requested by the user, which increases the volume of data transmitted. | [cnumr best practices (3rd edition) BP_032](https://github.com/cnumr/best-practices/blob/main/chapters/BP_032_fr.md) | 🚫 | 🚫 | 🚀 | 🚫 | 🚫 | 🚫 | 🚀 | | | Resize images browser-side | Do not resize images using the HEIGHT and WIDTH attributes of the HTML code. This approach requires transferring these images to their original size, wasting bandwidth and CPU cycles. | [cnumr best practices (3rd edition) BP_034](https://github.com/cnumr/best-practices/blob/main/chapters/BP_034_fr.md) | 🚫 | 🚫 | 🚧 | 🚫 | 🚫 | 🚫 | 🚀 | | | Modify the DOM when traversing it | Modifying the DOM (Document Object Model) as you traverse it can lead to situations where the loop becomes very resource-intensive, especially CPU cycles. | [cnumr best practices (3rd edition) BP_041](https://github.com/cnumr/best-practices/blob/main/chapters/BP_041_fr.md) | 🚫 | 🚫 | 🚧 | 🚫 | 🚫 | 🚫 | 🚫 | -| | Edit DOM elements to make it invisible | When an element of the Document Object Model (DOM) needs to be modified by several properties, each change in style or content will generate a repaint or reflow. | [cnumr best practices (3rd edition) BP_042](https://github.com/cnumr/best-practices/blob/main/chapters/BP_042_fr.md) | 🚫 | 🚫 | 🚀 | 🚫 | 🚫 | 🚫 | 🚫 | +| | Edit DOM elements to make it invisible | When an element of the Document Object Model (DOM) needs to be modified by several properties, each change in style or content will generate a repaint or reflow. | [cnumr best practices (3rd edition) BP_042](https://github.com/cnumr/best-practices/blob/main/chapters/BP_042_fr.md) | 🚫 | 🚫 | 🚀 | 🚫 | 🚫 | 🚫 | 🚫 | | | ❓ | ❓ | ❓ | ❓ | ❓ | ✅ | ❓ | +| | Avoid Invariant Computations In Loop | Avoid evaluating expressions that remain constant across iterations inside loops. Move them outside the loop to save redundant computations. Tested on built-in functions : len(), sum(), sorted(), list(), tuple(), set(), dict(), max(), and min(). Should be extended to cover additional pure or deterministic functions in future iterations. | | ❓ | ❓ | ❓ | 🚧 | ❓ | ❓ | ❓ | +| ## Rules to be reworked / measured / clarified diff --git a/src/main/rules/GCI620/GCI620.json b/src/main/rules/GCI620/GCI620.json new file mode 100644 index 00000000..bd7fe02c --- /dev/null +++ b/src/main/rules/GCI620/GCI620.json @@ -0,0 +1,17 @@ +{ + "title": "Code efficiency - Avoid Invariant Computations In Loop", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant/Issue", + "constantCost": "5min" + }, + "tags": [ + "sobriety", + "environment", + "creedengo", + "bad-practice", + "eco-design" + ], + "defaultSeverity": "Major" +} diff --git a/src/main/rules/GCI620/Python/GCI620.asciidoc b/src/main/rules/GCI620/Python/GCI620.asciidoc new file mode 100644 index 00000000..517961e6 --- /dev/null +++ b/src/main/rules/GCI620/Python/GCI620.asciidoc @@ -0,0 +1,71 @@ +Evaluating expressions that remain constant across loop iterations leads to redundant computations, increasing execution time and energy consumption. +Such computations should be moved outside the loop to improve code performance and reduce environmental impact. + + +== Non Compliant Code Example + +[source,python] +---- +def process_data(data): + x = (1, 2, 3, 4) + + results = [] + for i in range(10_000): + n = len(x) # Noncompliant: invariant expression computed in the loop + results.append(n * i) + + return results +---- + +== Compliant Solution + +[source,python] +---- +def process_data(data): + x = (1, 2, 3, 4) + n = len(x) # Compliant: computed once outside the loop + + results = [] + for i in range(10_000): + results.append(n * i) + + return results +---- + +== Relevance Analysis + +This rule applies to all Python code where loops perform repeated evaluations of expressions that yield the same result in every iteration. + +In our benchmark, we focused on measuring the impact of a representative set of functions, namely len(), sum(), sorted(), list(), set(), max(), and min(). +Our implementation, however, goes beyond this set and currently supports detection for a broader range of functions, including len, sum, sorted, list, tuple, set, dict, max, and min. +This can easily be extended to cover additional pure or deterministic functions in future iterations. + + + +Avoiding such redundant operations improves both **runtime efficiency** and **carbon footprint**, especially in large-scale or iterative workloads. + +=== Configuration + +* Processor: Intel(R) Core(TM) i7-1165G7 @ 2.80GHz, 2800 MHz, 4 cores, 8 logical processors +* RAM: 8 GB +* CO2 Emissions Measurement: Using https://mlco2.github.io/codecarbon/[CodeCarbon] + +=== Context + +Two approaches were benchmarked: +- *Non-compliant:* The function is recomputed at every iteration. +- *Compliant:* The result of the function is stored once before the loop and reused. + +*Benchmarked functions:* len(), sum(), sorted(), list(), set(), max(), and min() + +=== Impact Analysis + +image::results_summary.png[] + +== Conclusion + +Avoiding invariant computations inside loops leads to better code efficiency and a measurable reduction in energy usage. This pattern is simple to detect and correct, and contributes meaningfully to greener Python practices. + +== References + +- https://en.wikipedia.org/wiki/Loop-invariant_code_motion diff --git a/src/main/rules/GCI620/Python/results_summary.png b/src/main/rules/GCI620/Python/results_summary.png new file mode 100644 index 00000000..2bcb6cf7 Binary files /dev/null and b/src/main/rules/GCI620/Python/results_summary.png differ