Skip to content

Conversation

@codeflash-ai
Copy link

@codeflash-ai codeflash-ai bot commented Oct 29, 2025

📄 27% (0.27x) speedup for get_majority_class in inference/core/workflows/core_steps/fusion/detections_consensus/v1.py

⏱️ Runtime : 1.38 milliseconds 1.08 milliseconds (best of 396 runs)

📝 Explanation and details

The optimization replaces a list comprehension with map and zip functions to eliminate intermediate list creation. Instead of building a complete list of tuples in memory with [(str(class_name), int(class_id)) for ...], the optimized version uses zip(map(str, detections["class_name"]), map(int, detections.class_id)) which creates an iterator that generates tuples on-demand.

Key changes:

  • Eliminates the list comprehension that creates a temporary list of all tuples
  • Uses map() to apply str() and int() conversions lazily
  • Counter consumes the iterator directly without materializing the full list

Why this is faster:

  • Avoids allocating memory for the entire intermediate list
  • Reduces memory allocations and garbage collection overhead
  • The iterator approach is more memory-efficient, especially beneficial for larger datasets

Performance benefits by test case size:

  • Small datasets (3-5 detections): 3-12% speedup due to reduced overhead
  • Large datasets (1000 detections): 18-45% speedup as memory allocation savings become more significant
  • The optimization shows increasing returns with larger input sizes, making it particularly valuable for high-throughput detection processing scenarios

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 73 Passed
🌀 Generated Regression Tests 38 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
⚙️ Existing Unit Tests and Runtime
Test File::Test Function Original ⏱️ Optimized ⏱️ Speedup
workflows/unit_tests/core_steps/fusion/test_detections_consensus.py::test_get_majority_class 12.0μs 11.2μs 6.59%✅
🌀 Generated Regression Tests and Runtime
from collections import Counter
from typing import Tuple

# imports
import pytest
from inference.core.workflows.core_steps.fusion.detections_consensus.v1 import \
    get_majority_class


# --- Function to test ---
# Simulate the Detections object from supervision
class DummyDetections:
    def __init__(self, class_names, class_ids):
        # Mimic the behavior of sv.Detections for required fields
        self.class_id = class_ids
        self._class_names = class_names

    def __getitem__(self, key):
        if key == "class_name":
            return self._class_names
        raise KeyError(key)
from inference.core.workflows.core_steps.fusion.detections_consensus.v1 import \
    get_majority_class

# --- Unit tests ---

# 1. Basic Test Cases

def test_single_class():
    # All detections are of the same class
    det = DummyDetections(['cat', 'cat', 'cat'], [0, 0, 0])
    codeflash_output = get_majority_class(det) # 7.85μs -> 6.97μs (12.5% faster)

def test_two_classes_majority_first():
    # 'dog' appears more than 'cat'
    det = DummyDetections(['dog', 'cat', 'dog', 'dog'], [1, 0, 1, 1])
    codeflash_output = get_majority_class(det) # 7.68μs -> 6.90μs (11.3% faster)

def test_two_classes_majority_second():
    # 'cat' appears more than 'dog'
    det = DummyDetections(['dog', 'cat', 'cat', 'cat'], [1, 0, 0, 0])
    codeflash_output = get_majority_class(det) # 7.49μs -> 6.91μs (8.46% faster)

def test_multiple_classes():
    # Three classes, one is majority
    det = DummyDetections(['bird', 'cat', 'dog', 'cat', 'cat'], [2, 0, 1, 0, 0])
    codeflash_output = get_majority_class(det) # 7.78μs -> 7.09μs (9.76% faster)

def test_class_id_as_string():
    # Class IDs as strings, should be converted to int
    det = DummyDetections(['cat', 'dog', 'cat'], ['0', '1', '0'])
    codeflash_output = get_majority_class(det) # 7.64μs -> 7.16μs (6.78% faster)

# 2. Edge Test Cases

def test_empty_detections():
    # No detections: should raise IndexError from most_common(1)[0]
    det = DummyDetections([], [])
    with pytest.raises(IndexError):
        get_majority_class(det) # 6.53μs -> 6.31μs (3.41% faster)

def test_tied_classes():
    # Two classes tied for majority: Counter.most_common returns the first in insertion order
    det = DummyDetections(['cat', 'dog'], [0, 1])
    # The first tuple in zip is ('cat', 0), so it should be returned
    codeflash_output = get_majority_class(det) # 7.45μs -> 6.89μs (8.09% faster)

def test_tied_classes_multiple():
    # Three classes, two tied for majority
    det = DummyDetections(['cat', 'dog', 'bird', 'dog', 'cat', 'bird'], [0, 1, 2, 1, 0, 2])
    # All appear twice, ('cat', 0) is first in zip
    codeflash_output = get_majority_class(det) # 7.97μs -> 6.81μs (17.0% faster)

def test_non_string_class_names():
    # Class names as integers, should be converted to string
    det = DummyDetections([1, 2, 1, 1], [10, 20, 10, 10])
    codeflash_output = get_majority_class(det) # 7.91μs -> 7.45μs (6.19% faster)

def test_negative_class_id():
    # Negative class_id values
    det = DummyDetections(['alien', 'alien', 'human'], [-1, -1, 0])
    codeflash_output = get_majority_class(det) # 7.04μs -> 6.67μs (5.56% faster)

def test_mixed_types_class_id():
    # Mixed int and str in class_id
    det = DummyDetections(['cat', 'cat', 'dog'], [0, '0', 1])
    codeflash_output = get_majority_class(det) # 7.21μs -> 6.66μs (8.16% faster)


def test_large_class_id_values():
    # Very large class_id values
    det = DummyDetections(['whale', 'whale', 'shark'], [999999999, 999999999, 888888888])
    codeflash_output = get_majority_class(det) # 7.85μs -> 7.26μs (8.14% faster)

def test_duplicate_class_names_different_ids():
    # Same class name, different class_id
    det = DummyDetections(['cat', 'cat', 'cat'], [0, 1, 0])
    # ('cat', 0) appears twice, ('cat', 1) once
    codeflash_output = get_majority_class(det) # 7.21μs -> 7.06μs (2.11% faster)

# 3. Large Scale Test Cases

def test_large_number_of_detections_single_majority():
    # 1000 detections, 600 of one class, 400 of another
    names = ['dog'] * 600 + ['cat'] * 400
    ids = [1] * 600 + [0] * 400
    det = DummyDetections(names, ids)
    codeflash_output = get_majority_class(det) # 112μs -> 78.0μs (44.6% faster)

def test_large_number_of_detections_tied():
    # 500 of each class
    names = ['dog'] * 500 + ['cat'] * 500
    ids = [1] * 500 + [0] * 500
    det = DummyDetections(names, ids)
    # ('dog', 1) is first in zip, so should be returned
    codeflash_output = get_majority_class(det) # 105μs -> 77.8μs (35.5% faster)

def test_large_number_of_unique_classes():
    # 1000 unique classes, each appears once
    names = [f'class_{i}' for i in range(1000)]
    ids = [i for i in range(1000)]
    det = DummyDetections(names, ids)
    # First tuple is ('class_0', 0)
    codeflash_output = get_majority_class(det) # 146μs -> 123μs (18.4% faster)

def test_large_majority_at_end():
    # Majority class appears in the last half
    names = ['cat'] * 400 + ['dog'] * 600
    ids = [0] * 400 + [1] * 600
    det = DummyDetections(names, ids)
    codeflash_output = get_majority_class(det) # 104μs -> 77.7μs (34.6% faster)

def test_large_majority_at_start():
    # Majority class appears in the first half
    names = ['dog'] * 600 + ['cat'] * 400
    ids = [1] * 600 + [0] * 400
    det = DummyDetections(names, ids)
    codeflash_output = get_majority_class(det) # 105μs -> 77.6μs (36.4% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from collections import namedtuple

# imports
import pytest
from inference.core.workflows.core_steps.fusion.detections_consensus.v1 import \
    get_majority_class


# function to test
# Simulate sv.Detections for testing purposes
class FakeDetections(dict):
    def __init__(self, class_names, class_ids):
        # store as dict for ["class_name"] access
        super().__init__()
        self["class_name"] = class_names
        self.class_id = class_ids
from inference.core.workflows.core_steps.fusion.detections_consensus.v1 import \
    get_majority_class

# --------- UNIT TESTS ---------

# --------- BASIC TEST CASES ---------

def test_single_class():
    # Only one class present
    det = FakeDetections(["cat"], [1])
    codeflash_output = get_majority_class(det) # 7.42μs -> 7.18μs (3.40% faster)

def test_two_classes_majority():
    # Two classes, one appears more often
    det = FakeDetections(["cat", "dog", "cat"], [1, 2, 1])
    codeflash_output = get_majority_class(det) # 7.51μs -> 7.24μs (3.63% faster)

def test_three_classes_tied():
    # Three classes, one appears most
    det = FakeDetections(["cat", "dog", "bird", "cat", "bird"], [1, 2, 3, 1, 3])
    codeflash_output = get_majority_class(det) # 7.60μs -> 7.08μs (7.28% faster)

def test_class_id_as_string():
    # Class IDs are strings, should be cast to int
    det = FakeDetections(["cat", "dog", "cat"], ["1", "2", "1"])
    codeflash_output = get_majority_class(det) # 7.31μs -> 6.99μs (4.56% faster)

def test_class_name_as_int():
    # Class names are ints, should be cast to str
    det = FakeDetections([1, 2, 1], [10, 20, 10])
    codeflash_output = get_majority_class(det) # 7.53μs -> 7.18μs (4.80% faster)

# --------- EDGE TEST CASES ---------

def test_empty_input():
    # No detections: should raise IndexError
    det = FakeDetections([], [])
    with pytest.raises(IndexError):
        get_majority_class(det) # 6.36μs -> 6.20μs (2.48% faster)

def test_tied_classes():
    # Two classes tied for majority, should return first in Counter order
    det = FakeDetections(["cat", "dog"], [1, 2])
    # Counter order is insertion order, so ("cat", 1) comes first
    codeflash_output = get_majority_class(det) # 6.81μs -> 6.95μs (2.09% slower)

def test_multiple_ties():
    # Three classes, all tied
    det = FakeDetections(["cat", "dog", "bird"], [1, 2, 3])
    # Should return first inserted, ("cat", 1)
    codeflash_output = get_majority_class(det) # 7.13μs -> 6.81μs (4.73% faster)

def test_non_string_class_names():
    # Class names are mixed types
    det = FakeDetections([None, True, 0], [1, 2, 3])
    codeflash_output = get_majority_class(det) # 7.36μs -> 7.03μs (4.78% faster)

def test_negative_class_ids():
    # Class IDs are negative
    det = FakeDetections(["cat", "dog", "cat"], [-1, -2, -1])
    codeflash_output = get_majority_class(det) # 7.03μs -> 6.78μs (3.69% faster)

def test_large_class_id():
    # Very large class IDs
    det = FakeDetections(["cat", "cat", "dog"], [999999999, 999999999, 1])
    codeflash_output = get_majority_class(det) # 7.54μs -> 7.04μs (7.10% faster)

def test_non_integer_class_id():
    # Class IDs are floats, should be cast to int
    det = FakeDetections(["cat", "dog", "cat"], [1.0, 2.0, 1.0])
    codeflash_output = get_majority_class(det) # 7.11μs -> 6.64μs (7.11% faster)

def test_class_id_zero():
    # Class ID zero
    det = FakeDetections(["cat", "dog", "cat"], [0, 1, 0])
    codeflash_output = get_majority_class(det) # 7.14μs -> 6.75μs (5.75% faster)


def test_non_list_inputs():
    # Inputs are tuples instead of lists
    det = FakeDetections(("cat", "dog", "cat"), (1, 2, 1))
    codeflash_output = get_majority_class(det) # 11.0μs -> 10.6μs (3.30% faster)

# --------- LARGE SCALE TEST CASES ---------

def test_large_majority():
    # 1000 elements, majority class
    names = ["cat"] * 600 + ["dog"] * 400
    ids = [1] * 600 + [2] * 400
    det = FakeDetections(names, ids)
    codeflash_output = get_majority_class(det) # 109μs -> 78.6μs (39.4% faster)

def test_large_tie():
    # 1000 elements, two classes tied
    names = ["cat"] * 500 + ["dog"] * 500
    ids = [1] * 500 + [2] * 500
    det = FakeDetections(names, ids)
    # Should return ("cat", 1) due to insertion order
    codeflash_output = get_majority_class(det) # 103μs -> 78.3μs (32.6% faster)

def test_large_many_classes():
    # 1000 elements, 10 classes, one majority
    names = []
    ids = []
    for i in range(10):
        names += [f"class{i}"] * (100 if i != 5 else 200)
        ids += [i] * (100 if i != 5 else 200)
    det = FakeDetections(names, ids)
    codeflash_output = get_majority_class(det) # 116μs -> 84.6μs (37.9% faster)

def test_large_all_unique():
    # 1000 elements, all unique classes
    names = [f"class{i}" for i in range(1000)]
    ids = list(range(1000))
    det = FakeDetections(names, ids)
    # Should return first inserted
    codeflash_output = get_majority_class(det) # 144μs -> 122μs (18.3% faster)

def test_large_all_tied():
    # 1000 elements, 500 pairs of two classes
    names = ["cat", "dog"] * 500
    ids = [1, 2] * 500
    det = FakeDetections(names, ids)
    codeflash_output = get_majority_class(det) # 104μs -> 77.9μs (33.9% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-get_majority_class-mhbv13ca and push.

Codeflash

The optimization replaces a list comprehension with `map` and `zip` functions to eliminate intermediate list creation. Instead of building a complete list of tuples in memory with `[(str(class_name), int(class_id)) for ...]`, the optimized version uses `zip(map(str, detections["class_name"]), map(int, detections.class_id))` which creates an iterator that generates tuples on-demand.

**Key changes:**
- Eliminates the list comprehension that creates a temporary list of all tuples
- Uses `map()` to apply `str()` and `int()` conversions lazily
- `Counter` consumes the iterator directly without materializing the full list

**Why this is faster:**
- Avoids allocating memory for the entire intermediate list
- Reduces memory allocations and garbage collection overhead
- The iterator approach is more memory-efficient, especially beneficial for larger datasets

**Performance benefits by test case size:**
- Small datasets (3-5 detections): 3-12% speedup due to reduced overhead
- Large datasets (1000 detections): 18-45% speedup as memory allocation savings become more significant
- The optimization shows increasing returns with larger input sizes, making it particularly valuable for high-throughput detection processing scenarios
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 October 29, 2025 10:36
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Oct 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants