Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⚡️ Speed up function merge_hooks by 939% #30

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

codeflash-ai[bot]
Copy link

@codeflash-ai codeflash-ai bot commented Jan 14, 2025

📄 939% (9.39x) speedup for merge_hooks in src/requests/sessions.py

⏱️ Runtime : 996 microseconds 95.9 microseconds (best of 134 runs)

📝 Explanation and details

Here is an optimized version of the provided Python program.

Explanation.

  1. Reduction of Intermediate Data Structures:
        - In the original merge_setting function, an intermediate merged_setting dictionary was created by converting the session settings to a list, then updated with the request settings, and then unnecessary None values were removed. This process involved creating and discarding several temporary data structures.
        - In the optimized version, we avoid creating an intermediate dictionary and directly populate merged_setting with the non-None values from the session and request settings through a single iteration.

  2. Early Termination on Empty Hooks.
        - The original merge_hooks checked for empty response hooks by comparing with []. The optimized version uses not directly which is slightly faster and more Pythonic.
        - This ensures we exit the function at the earliest possible point if the conditions for early termination are met.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 29 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 82.4%
🌀 Generated Regression Tests Details
from collections import OrderedDict

# imports
import pytest  # used for our unit tests
from src.requests.compat import Mapping
from src.requests.sessions import merge_hooks
from src.requests.utils import to_key_val_list

# unit tests

# Test cases for basic functionality
def test_both_none():
    codeflash_output = merge_hooks(None, None)

def test_request_none():
    codeflash_output = merge_hooks(None, {'response': [lambda x: x]})

def test_session_none():
    codeflash_output = merge_hooks({'response': [lambda x: x]}, None)

# Test cases for empty 'response' list handling
def test_session_empty_response():
    codeflash_output = merge_hooks({'response': [lambda x: x]}, {'response': []})

def test_request_empty_response():
    codeflash_output = merge_hooks({'response': []}, {'response': [lambda x: x]})

# Test cases for merging hooks
def test_both_non_empty_response():
    codeflash_output = merge_hooks({'response': [lambda x: x + 1]}, {'response': [lambda x: x]})

def test_multiple_keys():
    codeflash_output = merge_hooks({'response': [lambda x: x + 1], 'error': [lambda x: x - 1]}, {'response': [lambda x: x], 'error': [lambda x: x + 2]})

# Test cases for non-dictionary inputs


def test_request_none_value():
    codeflash_output = merge_hooks({'response': [None]}, {'response': [lambda x: x]})

def test_session_none_value():
    codeflash_output = merge_hooks({'response': [lambda x: x]}, {'response': [None]})

# Test cases for large scale inputs
def test_large_number_of_hooks_request():
    large_hooks = [lambda x: x] * 1000
    codeflash_output = merge_hooks({'response': large_hooks}, {'response': large_hooks})

def test_large_number_of_hooks_session():
    large_hooks = [lambda x: x] * 1000
    codeflash_output = merge_hooks({'response': [lambda x: x]}, {'response': large_hooks})

# Test cases for mixed key types
def test_different_keys():
    codeflash_output = merge_hooks({'response': [lambda x: x]}, {'error': [lambda x: x - 1]})

# Test cases for order preservation
def test_order_preservation():
    codeflash_output = merge_hooks({'response': [lambda x: x + 1]}, {'response': [lambda x: x]})
# 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 OrderedDict

# imports
import pytest  # used for our unit tests
from src.requests.compat import Mapping
from src.requests.sessions import merge_hooks
from src.requests.utils import to_key_val_list

# unit tests

# Basic Functionality Tests

def test_merge_hooks_both_none():
    codeflash_output = merge_hooks(None, None)

def test_merge_hooks_request_none():
    session_hooks = {'response': [lambda x: x]}
    codeflash_output = merge_hooks(None, session_hooks)

def test_merge_hooks_session_none():
    request_hooks = {'response': [lambda x: x]}
    codeflash_output = merge_hooks(request_hooks, None)

def test_merge_hooks_both_non_empty():
    request_hooks = {'response': [lambda x: x]}
    session_hooks = {'response': [lambda y: y]}
    expected = {'response': [lambda y: y, lambda x: x]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

# Edge Cases Tests

def test_merge_hooks_session_response_empty():
    request_hooks = {'response': [lambda x: x]}
    session_hooks = {'response': []}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_merge_hooks_request_response_empty():
    request_hooks = {'response': []}
    session_hooks = {'response': [lambda y: y]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_merge_hooks_both_response_empty():
    request_hooks = {'response': []}
    session_hooks = {'response': []}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_merge_hooks_different_keys():
    request_hooks = {'response': [lambda x: x]}
    session_hooks = {'pre_request': [lambda y: y]}
    expected = {'response': [lambda x: x], 'pre_request': [lambda y: y]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

# Complex Merging Tests

def test_merge_hooks_overlapping_keys():
    request_hooks = {'response': [lambda x: x1]}
    session_hooks = {'response': [lambda x: x2]}
    expected = {'response': [lambda x: x2, lambda x: x1]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_merge_hooks_with_none_values():
    request_hooks = {'response': [lambda x: x1], 'pre_request': None}
    session_hooks = {'response': [lambda x: x2], 'pre_request': [lambda y: y]}
    expected = {'response': [lambda x: x2, lambda x: x1], 'pre_request': [lambda y: y]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

# Large Scale Test Cases

def test_merge_hooks_large_number_of_hooks():
    request_hooks = {'response': [lambda x: x] * 1000}
    session_hooks = {'response': [lambda y: y] * 1000}
    expected = {'response': [lambda y: y] * 1000 + [lambda x: x] * 1000}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_merge_hooks_large_number_of_keys():
    request_hooks = {f'key_{i}': [lambda x: x] for i in range(1000)}
    session_hooks = {f'key_{i}': [lambda y: y] for i in range(1000)}
    expected = {f'key_{i}': [lambda y: y, lambda x: x] for i in range(1000)}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

# Performance and Scalability Tests

def test_merge_hooks_large_dictionaries():
    request_hooks = {f'key_{i}': [lambda x: x] for i in range(1000)}
    session_hooks = {f'key_{i}': [lambda y: y] for i in range(1000)}
    expected = {f'key_{i}': [lambda y: y, lambda x: x] for i in range(1000)}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

# Special Cases Tests


def test_merge_hooks_mixed_types_within_dict():
    request_hooks = {'response': [lambda x: x], 'pre_request': 'not a list'}
    session_hooks = {'response': [lambda y: y], 'pre_request': [lambda z: z]}
    expected = {'response': [lambda y: y, lambda x: x], 'pre_request': [lambda z: z]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

# Deterministic Behavior Tests

def test_merge_hooks_consistent_results():
    request_hooks = {'response': [lambda x: x]}
    session_hooks = {'response': [lambda y: y]}
    expected = {'response': [lambda y: y, lambda x: x]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)
    codeflash_output = merge_hooks(request_hooks, session_hooks)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

📢 Feedback on this optimization? Discord

Here is an optimized version of the provided Python program.



### Explanation.

1. **Reduction of Intermediate Data Structures**: 
    - In the original `merge_setting` function, an intermediate `merged_setting` dictionary was created by converting the session settings to a list, then updated with the request settings, and then unnecessary `None` values were removed. This process involved creating and discarding several temporary data structures.
    - In the optimized version, we avoid creating an intermediate dictionary and directly populate `merged_setting` with the non-None values from the session and request settings through a single iteration.

2. **Early Termination on Empty Hooks**.
    - The original `merge_hooks` checked for empty response hooks by comparing with `[]`. The optimized version uses `not` directly which is slightly faster and more Pythonic.
    - This ensures we exit the function at the earliest possible point if the conditions for early termination are met.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Jan 14, 2025
@codeflash-ai codeflash-ai bot requested a review from Saga4 January 14, 2025 21:07
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants