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 60% #7

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 Dec 22, 2024

📄 60% (0.60x) speedup for merge_hooks in src/requests/sessions.py

⏱️ Runtime : 189 microseconds 118 microseconds (best of 149 runs)

📝 Explanation and details

Sure, here is an optimized version of the given code. The primary improvements include avoiding unnecessary conversion to lists and dictionary updates, reducing dictionary lookups, and merging keys in place to reduce memory usage.

Here's a summary of changes made.

  1. Removed the to_key_val_list conversion and directly used the dictionaries for updating, avoiding the extra list creation step.
  2. Merged request_setting directly into merged_setting, eliminating the need for two update steps.
  3. Removed keys with None values during the update step itself to avoid a separate loop for deletion.

These optimizations reduce both the time complexity by eliminating unnecessary operations and the space complexity by avoiding extra list creations.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 27 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

# Dummy hook functions for testing
def hook1(response):
    pass

def hook2(response):
    pass

def test_basic_non_overlapping_keys():
    request_hooks = {'response': [hook1]}
    session_hooks = {'error': [hook2]}
    expected = {'response': [hook1], 'error': [hook2]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_basic_overlapping_keys():
    request_hooks = {'response': [hook1]}
    session_hooks = {'response': [hook2]}
    expected = {'response': [hook1, hook2]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_session_hooks_none():
    request_hooks = {'response': [hook1]}
    session_hooks = None
    expected = {'response': [hook1]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_request_hooks_none():
    request_hooks = None
    session_hooks = {'response': [hook2]}
    expected = {'response': [hook2]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

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

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



def test_mixed_types_in_hooks():
    request_hooks = {'response': [hook1, 'string_hook', 123]}
    session_hooks = {'response': [hook2, 'another_string_hook', 456]}
    expected = {'response': [hook1, 'string_hook', 123, hook2, 'another_string_hook', 456]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_large_scale_hooks():
    request_hooks = {'response': [hook1] * 1000}
    session_hooks = {'response': [hook2] * 1000}
    expected = {'response': [hook1] * 1000 + [hook2] * 1000}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_both_hooks_empty_dict():
    request_hooks = {}
    session_hooks = {}
    expected = {}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_both_hooks_none():
    request_hooks = None
    session_hooks = None
    expected = None
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_session_hooks_with_none_values():
    request_hooks = {'response': [hook1]}
    session_hooks = {'response': None}
    expected = {'response': [hook1]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_request_hooks_with_none_values():
    request_hooks = {'response': None}
    session_hooks = {'response': [hook2]}
    expected = {'response': [hook2]}
    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.

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

def test_both_hooks_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)

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

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

def test_both_hooks_none():
    request_hooks = None
    session_hooks = None
    expected = None
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_empty_dictionaries():
    request_hooks = {}
    session_hooks = {}
    expected = {}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_non_list_values():
    request_hooks = {'response': 'not a list'}
    session_hooks = {'response': 'not a list'}
    expected = {'response': 'not a list'}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

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

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

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

def test_large_number_of_hooks():
    request_hooks = {'response': [lambda x: x for _ in range(1000)]}
    session_hooks = {'response': [lambda y: y for _ in range(1000)]}
    expected = {'response': [lambda y: y for _ in range(1000)] + [lambda x: x for _ in range(1000)]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_nested_dictionaries():
    request_hooks = {'response': [{'key1': 'value1'}, {'key2': 'value2'}]}
    session_hooks = {'response': [{'key3': 'value3'}, {'key4': 'value4'}]}
    expected = {'response': [{'key3': 'value3'}, {'key4': 'value4'}, {'key1': 'value1'}, {'key2': 'value2'}]}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_different_dict_class():
    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, dict_class=dict)

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

def test_mixed_key_types():
    request_hooks = {'response': [lambda x: x], 1: 'integer key'}
    session_hooks = {'response': [lambda y: y], (2, 3): 'tuple key'}
    expected = {'response': [lambda y: y, lambda x: x], 1: 'integer key', (2, 3): 'tuple key'}
    codeflash_output = merge_hooks(request_hooks, session_hooks)

def test_hooks_with_multiple_keys():
    request_hooks = {'response': [lambda x: x], 'pre_request': [lambda z: z]}
    session_hooks = {'response': [lambda y: y], 'post_request': [lambda w: w]}
    expected = {'response': [lambda y: y, lambda x: x], 'pre_request': [lambda z: z], 'post_request': [lambda w: w]}
    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

Sure, here is an optimized version of the given code. The primary improvements include avoiding unnecessary conversion to lists and dictionary updates, reducing dictionary lookups, and merging keys in place to reduce memory usage.



Here's a summary of changes made.
1. Removed the `to_key_val_list` conversion and directly used the dictionaries for updating, avoiding the extra list creation step.
2. Merged `request_setting` directly into `merged_setting`, eliminating the need for two update steps.
3. Removed keys with `None` values during the update step itself to avoid a separate loop for deletion.
   
These optimizations reduce both the time complexity by eliminating unnecessary operations and the space complexity by avoiding extra list creations.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Dec 22, 2024
@codeflash-ai codeflash-ai bot requested a review from alvin-r December 22, 2024 05:21
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