Skip to content

Conversation

@codeflash-ai
Copy link

@codeflash-ai codeflash-ai bot commented Nov 4, 2025

📄 627% (6.27x) speedup for _build_filters_and_metadata in mem0/memory/main.py

⏱️ Runtime : 1.67 milliseconds 229 microseconds (best of 33 runs)

📝 Explanation and details

The optimized code achieves a 626% speedup through two key changes that eliminate unnecessary overhead:

1. Replace deepcopy() with shallow copy()

  • Original code uses deepcopy() on input_metadata and input_filters, which recursively copies all nested objects
  • Optimized code uses shallow copy(), which only copies the top-level dictionary
  • This is safe because the function only adds/modifies top-level keys, never mutating nested values
  • Line profiler shows this change alone reduces the two most expensive operations from ~12.7ms to ~0.23ms total

2. Replace list tracking with integer counter

  • Original code maintains session_ids_provided = [] and calls append() for each session ID
  • Optimized code uses session_ids_provided = 0 and increments with += 1
  • Eliminates list object allocation and method calls for a simple existence check

Performance benefits by test case type:

  • Simple cases (basic session IDs): 5-17% faster due to counter optimization
  • Cases with input dicts: 200-500% faster due to shallow copy optimization
  • Large-scale cases (500+ dict entries): Up to 7000% faster, as deepcopy overhead scales with dict size while copy() remains constant

The optimizations are particularly effective when input_metadata or input_filters contain large or nested dictionaries, which is common in production memory management scenarios.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 348 Passed
⏪ Replay Tests 8 Passed
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
from copy import deepcopy

# imports
import pytest
from mem0.memory.main import _build_filters_and_metadata


# Simulate the ValidationError used in the function
class Mem0ValidationError(Exception):
    def __init__(self, message, error_code, details, suggestion):
        super().__init__(message)
        self.message = message
        self.error_code = error_code
        self.details = details
        self.suggestion = suggestion
from mem0.memory.main import _build_filters_and_metadata

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

# 1. Basic Test Cases

def test_basic_user_id_only():
    """Test with only user_id provided, no metadata or filters."""
    meta, filt = _build_filters_and_metadata(user_id="u1") # 1.61μs -> 1.53μs (5.57% faster)

def test_basic_agent_id_only():
    """Test with only agent_id provided."""
    meta, filt = _build_filters_and_metadata(agent_id="a1") # 1.55μs -> 1.39μs (11.9% faster)

def test_basic_run_id_only():
    """Test with only run_id provided."""
    meta, filt = _build_filters_and_metadata(run_id="r1") # 1.57μs -> 1.48μs (6.64% faster)

def test_basic_multiple_session_ids():
    """Test with user_id and agent_id provided."""
    meta, filt = _build_filters_and_metadata(user_id="u1", agent_id="a1") # 1.72μs -> 1.52μs (12.7% faster)

def test_basic_all_session_ids():
    """Test with all three session IDs provided."""
    meta, filt = _build_filters_and_metadata(user_id="u1", agent_id="a1", run_id="r1") # 1.81μs -> 1.65μs (9.91% faster)

def test_basic_with_metadata_and_filters():
    """Test with input_metadata and input_filters provided."""
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        input_metadata={"foo": "bar"},
        input_filters={"baz": 123}
    ) # 7.99μs -> 1.63μs (392% faster)

def test_basic_with_actor_id():
    """Test with actor_id provided."""
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id="act1") # 1.61μs -> 1.43μs (12.8% faster)

def test_basic_with_actor_id_and_input_filters_actor_id():
    """Test precedence: explicit actor_id overrides input_filters['actor_id']."""
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        actor_id="act1",
        input_filters={"actor_id": "act2"}
    ) # 5.77μs -> 1.67μs (246% faster)

def test_basic_with_input_filters_actor_id_only():
    """Test with actor_id only in input_filters."""
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        input_filters={"actor_id": "act2"}
    ) # 5.38μs -> 1.69μs (218% faster)

def test_basic_with_input_metadata_and_filters_and_all_ids():
    """Test with all parameters provided."""
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        agent_id="a1",
        run_id="r1",
        actor_id="act1",
        input_metadata={"foo": "bar"},
        input_filters={"baz": 123, "actor_id": "act2"}
    ) # 7.50μs -> 1.91μs (294% faster)

# 2. Edge Test Cases




def test_edge_input_metadata_is_mutated():
    """Test that input_metadata is not mutated."""
    input_metadata = {"foo": "bar"}
    meta, _ = _build_filters_and_metadata(user_id="u1", input_metadata=input_metadata) # 7.07μs -> 2.06μs (244% faster)

def test_edge_input_filters_is_mutated():
    """Test that input_filters is not mutated."""
    input_filters = {"baz": 123}
    _, filt = _build_filters_and_metadata(user_id="u1", input_filters=input_filters) # 5.77μs -> 1.66μs (248% faster)

def test_edge_input_metadata_and_filters_are_none():
    """Test with None for input_metadata and input_filters."""
    meta, filt = _build_filters_and_metadata(user_id="u1", input_metadata=None, input_filters=None) # 1.61μs -> 1.52μs (6.19% faster)

def test_edge_input_metadata_and_filters_are_empty_dicts():
    """Test with empty dicts for input_metadata and input_filters."""
    meta, filt = _build_filters_and_metadata(user_id="u1", input_metadata={}, input_filters={}) # 1.64μs -> 1.49μs (10.2% faster)

def test_edge_actor_id_falsey_values():
    """Test that falsey actor_id values (None, '', 0) do not get added."""
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id=None) # 1.60μs -> 1.42μs (13.0% faster)
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id="") # 719ns -> 646ns (11.3% faster)
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id=0) # 519ns -> 508ns (2.17% faster)

def test_edge_input_filters_actor_id_falsey():
    """Test that actor_id in input_filters is handled correctly for falsey values."""
    meta, filt = _build_filters_and_metadata(user_id="u1", input_filters={"actor_id": None}) # 6.22μs -> 1.57μs (297% faster)
    meta, filt = _build_filters_and_metadata(user_id="u1", input_filters={"actor_id": ""}) # 2.45μs -> 749ns (227% faster)
    meta, filt = _build_filters_and_metadata(user_id="u1", input_filters={"actor_id": 0}) # 1.81μs -> 512ns (254% faster)

def test_edge_input_metadata_and_filters_shared_keys():
    """Test that input_metadata and input_filters can have overlapping keys."""
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        input_metadata={"shared": "meta"},
        input_filters={"shared": "filter"}
    ) # 6.42μs -> 1.46μs (339% faster)

def test_edge_input_metadata_and_filters_are_nested():
    """Test with nested dicts in input_metadata and input_filters."""
    input_metadata = {"nested": {"foo": "bar"}}
    input_filters = {"nested": {"baz": 123}}
    meta, filt = _build_filters_and_metadata(user_id="u1", input_metadata=input_metadata, input_filters=input_filters) # 9.61μs -> 1.59μs (505% faster)

def test_edge_non_string_session_ids():
    """Test that non-string session IDs are accepted."""
    meta, filt = _build_filters_and_metadata(user_id=123, agent_id=456, run_id=789) # 1.92μs -> 1.69μs (13.8% faster)

def test_edge_non_string_actor_id():
    """Test that non-string actor_id is accepted."""
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id=999) # 1.60μs -> 1.41μs (13.9% faster)

# 3. Large Scale Test Cases

def test_large_scale_many_metadata_and_filters():
    """Test with large input_metadata and input_filters dicts."""
    input_metadata = {f"meta_{i}": i for i in range(500)}
    input_filters = {f"filter_{i}": i for i in range(500)}
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        agent_id="a1",
        run_id="r1",
        input_metadata=input_metadata,
        input_filters=input_filters,
        actor_id="act1"
    ) # 386μs -> 5.36μs (7106% faster)
    # Check all keys from input_metadata and input_filters are present
    for i in range(500):
        pass

def test_large_scale_unique_session_ids():
    """Test with unique session IDs for each call in a loop."""
    for i in range(100):
        meta, filt = _build_filters_and_metadata(user_id=f"user{i}", agent_id=f"agent{i}", run_id=f"run{i}") # 55.6μs -> 51.2μs (8.75% faster)

def test_large_scale_actor_id_variety():
    """Test with many different actor_id values."""
    for i in range(100):
        meta, filt = _build_filters_and_metadata(user_id="u1", actor_id=f"actor_{i}") # 43.9μs -> 40.6μs (8.11% faster)

def test_large_scale_nested_metadata_and_filters():
    """Test with large nested dicts in input_metadata and input_filters."""
    input_metadata = {"nested": {f"meta_{i}": i for i in range(100)}}
    input_filters = {"nested": {f"filter_{i}": i for i in range(100)}}
    meta, filt = _build_filters_and_metadata(user_id="u1", input_metadata=input_metadata, input_filters=input_filters) # 88.4μs -> 1.66μs (5218% faster)

def test_large_scale_no_mutation_of_inputs():
    """Test that large input dicts are not mutated."""
    input_metadata = {f"meta_{i}": [i] for i in range(100)}
    input_filters = {f"filter_{i}": [i] for i in range(100)}
    orig_metadata = deepcopy(input_metadata)
    orig_filters = deepcopy(input_filters)
    _build_filters_and_metadata(user_id="u1", input_metadata=input_metadata, input_filters=input_filters) # 196μs -> 2.75μs (7060% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from copy import deepcopy
from typing import Any, Dict, Optional

# imports
import pytest  # used for our unit tests
from mem0.memory.main import _build_filters_and_metadata


# Minimal custom exception for testing (since mem0.exceptions is unavailable here)
class Mem0ValidationError(Exception):
    def __init__(self, message, error_code, details, suggestion):
        super().__init__(message)
        self.message = message
        self.error_code = error_code
        self.details = details
        self.suggestion = suggestion
from mem0.memory.main import _build_filters_and_metadata

# unit tests

# 1. Basic Test Cases

def test_only_user_id():
    # Only user_id provided, no metadata/filters
    meta, filt = _build_filters_and_metadata(user_id="u1") # 1.80μs -> 1.69μs (6.77% faster)

def test_only_agent_id():
    # Only agent_id provided
    meta, filt = _build_filters_and_metadata(agent_id="a1") # 1.70μs -> 1.45μs (17.1% faster)

def test_only_run_id():
    # Only run_id provided
    meta, filt = _build_filters_and_metadata(run_id="r1") # 1.61μs -> 1.45μs (10.8% faster)

def test_user_and_agent_id():
    # Both user_id and agent_id provided
    meta, filt = _build_filters_and_metadata(user_id="u1", agent_id="a1") # 1.77μs -> 1.59μs (11.1% faster)

def test_user_and_run_id():
    # user_id and run_id provided
    meta, filt = _build_filters_and_metadata(user_id="u1", run_id="r1") # 1.78μs -> 1.54μs (15.5% faster)

def test_agent_and_run_id():
    # agent_id and run_id provided
    meta, filt = _build_filters_and_metadata(agent_id="a1", run_id="r1") # 1.71μs -> 1.49μs (14.7% faster)

def test_all_ids():
    # All three session IDs provided
    meta, filt = _build_filters_and_metadata(user_id="u1", agent_id="a1", run_id="r1") # 1.88μs -> 1.71μs (9.87% faster)

def test_with_input_metadata_and_filters():
    # Provided input_metadata and input_filters
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        input_metadata={"foo": "bar"},
        input_filters={"baz": "qux"}
    ) # 7.91μs -> 1.75μs (353% faster)

def test_with_actor_id_only():
    # Provided actor_id and user_id
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id="act1") # 1.55μs -> 1.47μs (5.66% faster)

def test_with_actor_id_and_input_filters_actor_id():
    # actor_id param should take precedence over input_filters["actor_id"]
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        actor_id="act1",
        input_filters={"actor_id": "act2", "foo": "bar"}
    ) # 6.28μs -> 1.67μs (277% faster)

def test_with_input_filters_actor_id_only():
    # actor_id not provided, but input_filters["actor_id"] is
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        input_filters={"actor_id": "act2", "foo": "bar"}
    ) # 5.87μs -> 1.64μs (258% faster)

# 2. Edge Test Cases




def test_input_metadata_and_filters_are_not_mutated():
    # Ensure input dicts are not mutated
    imeta = {"foo": "bar"}
    ifilt = {"baz": "qux"}
    _build_filters_and_metadata(user_id="u1", input_metadata=imeta, input_filters=ifilt) # 8.58μs -> 2.14μs (301% faster)

def test_input_metadata_overlapping_keys():
    # input_metadata has a key that is overwritten by session id
    imeta = {"user_id": "old", "foo": "bar"}
    meta, filt = _build_filters_and_metadata(user_id="new", input_metadata=imeta) # 6.15μs -> 1.72μs (257% faster)

def test_input_filters_overlapping_keys():
    # input_filters has a key that is overwritten by session id
    ifilt = {"user_id": "old", "baz": "qux"}
    meta, filt = _build_filters_and_metadata(user_id="new", input_filters=ifilt) # 5.55μs -> 1.64μs (238% faster)

def test_actor_id_not_added_to_metadata():
    # actor_id should not be added to base_metadata_template
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id="act1") # 1.57μs -> 1.43μs (10.1% faster)

def test_input_metadata_and_filters_are_deepcopied():
    # Nested dicts in input_metadata/input_filters are deepcopied
    imeta = {"foo": {"bar": 1}}
    ifilt = {"baz": {"qux": 2}}
    meta, filt = _build_filters_and_metadata(user_id="u1", input_metadata=imeta, input_filters=ifilt) # 9.78μs -> 1.62μs (504% faster)
    meta["foo"]["bar"] = 99
    filt["baz"]["qux"] = 99

def test_actor_id_none_and_input_filters_actor_id_none():
    # Both actor_id and input_filters["actor_id"] are None: should not add actor_id
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id=None, input_filters={"actor_id": None}) # 5.26μs -> 1.62μs (224% faster)



def test_large_input_metadata_and_filters():
    # Large input_metadata and input_filters, ensure performance and correctness
    big_meta = {f"meta_{i}": i for i in range(500)}
    big_filt = {f"filt_{i}": i for i in range(500)}
    meta, filt = _build_filters_and_metadata(user_id="u1", input_metadata=big_meta, input_filters=big_filt) # 389μs -> 5.54μs (6932% faster)
    for i in range(500):
        pass

def test_many_session_ids_and_large_metadata():
    # All session IDs and large metadata/filters
    big_meta = {f"meta_{i}": i for i in range(300)}
    big_filt = {f"filt_{i}": i for i in range(300)}
    meta, filt = _build_filters_and_metadata(
        user_id="u1",
        agent_id="a1",
        run_id="r1",
        input_metadata=big_meta,
        input_filters=big_filt,
        actor_id="act1"
    ) # 235μs -> 3.68μs (6312% faster)
    for i in range(300):
        pass

def test_large_actor_id_string():
    # Very large actor_id string
    big_actor = "a" * 500
    meta, filt = _build_filters_and_metadata(user_id="u1", actor_id=big_actor) # 1.66μs -> 1.53μs (8.69% faster)

def test_large_nested_metadata_and_filters():
    # Deeply nested dicts in input_metadata/input_filters
    nested_meta = {"foo": {"bar": {"baz": list(range(100))}}}
    nested_filt = {"alpha": {"beta": {"gamma": list(range(100))}}}
    meta, filt = _build_filters_and_metadata(user_id="u1", input_metadata=nested_meta, input_filters=nested_filt) # 54.0μs -> 1.71μs (3066% faster)

def test_performance_with_many_calls():
    # Call the function many times to check for consistent behavior and no memory leaks
    for i in range(100):
        meta, filt = _build_filters_and_metadata(user_id=f"user_{i}", agent_id=f"agent_{i}") # 50.1μs -> 45.7μs (9.51% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
⏪ Replay Tests and Runtime
Test File::Test Function Original ⏱️ Optimized ⏱️ Speedup
test_pytest_testsvector_storestest_opensearch_py_testsvector_storestest_upstash_vector_py_testsllmstest_l__replay_test_0.py::test_mem0_memory_main__build_filters_and_metadata 8.04μs 7.73μs 4.00%✅

To edit these changes git checkout codeflash/optimize-_build_filters_and_metadata-mhk06qj1 and push.

Codeflash Static Badge

The optimized code achieves a **626% speedup** through two key changes that eliminate unnecessary overhead:

**1. Replace `deepcopy()` with shallow `copy()`**
- Original code uses `deepcopy()` on `input_metadata` and `input_filters`, which recursively copies all nested objects
- Optimized code uses shallow `copy()`, which only copies the top-level dictionary
- This is safe because the function only adds/modifies top-level keys, never mutating nested values
- Line profiler shows this change alone reduces the two most expensive operations from ~12.7ms to ~0.23ms total

**2. Replace list tracking with integer counter**
- Original code maintains `session_ids_provided = []` and calls `append()` for each session ID
- Optimized code uses `session_ids_provided = 0` and increments with `+= 1`
- Eliminates list object allocation and method calls for a simple existence check

**Performance benefits by test case type:**
- **Simple cases** (basic session IDs): 5-17% faster due to counter optimization
- **Cases with input dicts**: 200-500% faster due to shallow copy optimization  
- **Large-scale cases** (500+ dict entries): Up to 7000% faster, as `deepcopy` overhead scales with dict size while `copy()` remains constant

The optimizations are particularly effective when `input_metadata` or `input_filters` contain large or nested dictionaries, which is common in production memory management scenarios.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 November 4, 2025 03:22
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Nov 4, 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.

1 participant