Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- [#197](https://github.com/green-code-initiative/creedengo-java/issues/197) Deprecation of GCI67 for java ("++i" instead of "i++")
- update internal library versions
- [#482](https://github.com/green-code-initiative/creedengo-rules-specifications/pull/482) Complete GCI91 documentation to prove relevance for Python language

### Deleted

Expand Down
2 changes: 1 addition & 1 deletion RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Some are applicable for different technologies.
| GCI88 | Dispose resource asynchronously | Resources that implement `IAsyncDisposable` should be disposed asynchronously | | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | ✅ | 🚫 | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI88) |
| GCI89 | Avoid using function cache without limit | If a function has decorators without max size cache, the program will store unlimited data | | ❓ | ❓ | ❓ | ✅ | ❓ | ❓ | ❓ | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI89) |
| GCI90 | Use `Cast` instead of `Select` to cast | `Cast` is optimized for this scenario and should be used | | ❓ | ❓ | ❓ | ❓ | ❓ | ✅ | ❓ | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI90) |
| GCI91 | Use filter feature before sort elements | Filter elements before sorting them for improved efficiency | | 🚧 | ❓ | ❓ | | ❓ | ✅ | ❓ | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI91) |
| GCI91 | Use filter feature before sort elements | Filter elements before sorting them for improved efficiency | | 🚧 | ❓ | ❓ | 🚀 | ❓ | ✅ | ❓ | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI91) |
| GCI92 | Use string.Length instead of comparison with empty string | Comparing a string to an empty string is unnecessary and can be replaced by a call to `string.Length` which is more performant and more readable. | | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | ✅ | 🚫 | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI92) |
| GCI93 | Return `Task` directly | Consider returning a `Task` directly instead of a single `await` | | ❓ | ❓ | ❓ | ❓ | ❓ | ✅ | ❓ | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI93) |
| GCI94 | Use orElseGet instead of orElse | Parameter of orElse() is evaluated, even when having a non-empty Optional. Supplier method of orElseGet passed as an argument is only executed when an Optional value isn’t present. Therefore, using orElseGet() will save computing time. | [Optimized use of Java Optional Else](https://github.com/green-code-initiative/creedengo-challenge/issues/77) | ✅ | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | [documentation](https://github.com/green-code-initiative/creedengo-rules-specifications/tree/main/src/main/rules/GCI94) |
Expand Down
61 changes: 61 additions & 0 deletions src/main/rules/GCI91/python/GCI91.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
= GCI91 Rule Feasibility and Optimization Report: Use Filter Before Sort

== 1. Objective and Context
The purpose of this report is to evaluate the applicability and green software metrics of rule GCI91 (Use filter feature before sort elements) for the Python language. This analysis aims to justify changing its status from pending evaluation to active within the standard matrix.
In data processing pipelines, sorting algorithms are highly intensive operations. This investigation provides data-driven evidence that reducing the dataset size via filtering prior to executing a sort operation drastically cuts power consumption, execution time, and memory overhead.

== 2. Implementation Feasibility in Static Code Analysis
From an AST (Abstract Syntax Tree) perspective, detecting this anti-pattern in Python code is highly straightforward and fully implementable within the Creedengo static analysis engine.

The analyzer needs to inspect the AST for the following sequence:
- A sorting mechanism operation, such as the built-in sorted() function or a .sort() method call on a list object.
- A list comprehension or loop filtering pattern wrapped immediately around or executed right after the sorting operation on the same dataset.

When the sorting node is identified as an input directly feeding a filter constraint, the rule engine can easily raise a violation issue recommending a structural inversion (filtering first, then sorting).

== 3. Benchmark and Technical Protocol
To demonstrate optimization efficiency, a hardware-level stress test was executed.
- Dataset 1 (Performance Benchmark): A list of 1,000,000 random integers.
- Dataset 2 (Energy Benchmark): A list of 2,000,000 random integers ranging from 1 to 100.
- Filter Condition: Retaining elements with a value strictly greater than 90 (filtering out approximately 90% of the dataset).
- Measurement Engine: CodeCarbon integration linked with system-level Intel/AMD RAPL (Running Average Power Limit) energy sensors to track raw hardware power draws, alongside tracemalloc for memory peaks.
- Iterations: 10 sequential loops with the Python Garbage Collector disabled to eliminate cleanup bias and capture raw processing energy.

== 4. Detailed Green Software Metrics

=== Part A: Raw Performance and Memory Results (1 Million Items)

Non-Compliant Pattern (Sort then Filter):
- Execution Time: 1.7046 sec
- Peak RAM Allocation: 11.41 MB

Compliant Pattern (Filter then Sort):
- Execution Time: 0.3639 sec
- Peak RAM Allocation: 1.87 MB

=== Part B: Hardware Energy and Carbon Relevance (2 Million Items)

Non-Compliant Pattern (Sort then Filter):
- CPU Energy Consumption: < 0.000001 kWh
- RAM Energy Consumption: 0.000009 kWh
- Carbon Footprint Estimate: 0.5258 mg CO2

Compliant Pattern (Filter then Sort):
- CPU Energy Consumption: < 0.000001 kWh
- RAM Energy Consumption: 0.000002 kWh
- Carbon Footprint Estimate: 0.0979 mg CO2

NOTE: CPU energy is reported here in kWh for consistency with the measurement output; values shown as 0.000000 kWh are below the display precision/measurement resolution and should not be interpreted as exact zero consumption.

=== Part C: Optimization Ratios
- Execution Time Reduction: Divided by 4.68
- Peak RAM Buffer Draw Optimization: Divided by 6.10
- Total Carbon Footprint Reduction: Divided by 5.37
- RAM Energy Draw Optimization: Divided by 4.50

== 5. Algorithmic and Structural Analysis
The massive variance in resource draw is mathematically sound. Python uses Timsort, an adaptive sorting algorithm derived from Merge Sort and Insertion Sort, operating with a worst-case time complexity of O(n log n).
By executing the sorting operation on the unfiltered dataset, the CPU must compute relationships across the complete dataset. Inverting the logic reduces the parameter 'n' by roughly 90% before it hits Timsort. Consequently, the CPU performs significantly fewer operations because the sorting work drops from roughly n log n to m log m after filtering, and the memory runtime architecture skips allocating large, volatile pointer lists for discarded elements, protecting the RAM buffer from heavy peaks.

== 6. Recommendation
Based on clear empirical evidence tracking hardware power consumption, implementing GCI91 delivers substantial infrastructure relief and carbon reduction without adding syntax complexity. We recommend shifting the rule state to applicable for Python.
Loading