Skip to content

Conversation

@codeflash-ai
Copy link

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

📄 213% (2.13x) speedup for get_actual_routes in litellm/proxy/auth/auth_checks.py

⏱️ Runtime : 1.43 milliseconds 455 microseconds (best of 250 runs)

📝 Explanation and details

The optimized code achieves a 213% speedup by eliminating expensive exception handling and reducing method lookup overhead in the core loop.

Key Performance Optimizations:

  1. Replaced try/except with dictionary lookup: The original code used LiteLLMRoutes[route_name] which throws KeyError for invalid routes, requiring expensive exception handling. The optimized version uses LiteLLMRoutes.__members__.get(route_name) which returns None for missing keys without exceptions. Exception handling in Python is significantly more costly than dictionary lookups.

  2. Cached method references: The optimized code caches actual_routes.extend and actual_routes.append as local variables (extend_actual_routes, append_actual_routes). This eliminates repeated attribute lookups in the loop, which is especially beneficial for the large-scale test cases.

  3. Simplified value handling: Removed the unnecessary list() conversion for sets since extend() accepts any iterable, including sets directly.

Performance Impact Analysis:
The function is called in authentication flows (as shown in handle_jwt.py), where route access permissions are validated. The optimization is particularly effective for:

  • Large-scale scenarios: Test cases with 500-1000 route names show 200-267% speedups, indicating this function may handle bulk route validation
  • Mixed valid/invalid routes: 19-20% improvements for realistic mixed scenarios where some route names don't exist in the enum
  • High-frequency calls: Given its use in auth checks, this function likely executes frequently in production workloads

The optimizations maintain identical behavior and output while dramatically reducing CPU overhead, especially beneficial when validating admin route permissions in authentication-heavy applications.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 37 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 70.0%
🌀 Generated Regression Tests and Runtime
from enum import Enum

# imports
import pytest
from litellm.proxy.auth.auth_checks import get_actual_routes


class LiteLLMRoutes(Enum):
    # Some routes map to sets
    CHAT = {"chat/completions", "chat/stream"}
    # Some routes map to lists
    EMBEDDINGS = ["embeddings", "embeddings/stream"]
    # Some routes map to single string in a list
    TEXT = ["text/completions"]
    # Some routes map to empty set
    EMPTY_SET = set()
    # Some routes map to empty list
    EMPTY_LIST = []
    # Some routes map to a set with one element
    SINGLE_SET = {"single/route"}
    # Some routes map to a list with one element
    SINGLE_LIST = ["single/list/route"]

    # For edge cases, route names that are not present will be handled
from litellm.proxy.auth.auth_checks import get_actual_routes

# unit tests

# 1. Basic Test Cases

def test_basic_multiple_routes():
    # Test with multiple valid route names mapping to sets and lists
    allowed_routes = ["CHAT", "EMBEDDINGS", "TEXT"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 2.56μs -> 2.33μs (9.82% faster)
    # The order of set elements is not guaranteed, so sort for comparison
    expected = sorted(["chat/completions", "chat/stream"]) + ["embeddings", "embeddings/stream", "text/completions"]

def test_basic_single_route_set():
    # Test with a single valid route mapping to a set
    allowed_routes = ["CHAT"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 1.71μs -> 1.99μs (14.1% slower)
    expected = ["chat/completions", "chat/stream"]

def test_basic_single_route_list():
    # Test with a single valid route mapping to a list
    allowed_routes = ["EMBEDDINGS"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 1.63μs -> 1.92μs (14.8% slower)
    expected = ["embeddings", "embeddings/stream"]

def test_basic_single_route_single_list():
    # Test with a route mapping to a list with one element
    allowed_routes = ["SINGLE_LIST"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 1.61μs -> 1.85μs (12.9% slower)
    expected = ["single/list/route"]

def test_basic_single_route_single_set():
    # Test with a route mapping to a set with one element
    allowed_routes = ["SINGLE_SET"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 1.67μs -> 1.92μs (12.7% slower)
    expected = ["single/route"]

# 2. Edge Test Cases

def test_edge_route_not_found():
    # Test with a route name not present in LiteLLMRoutes
    allowed_routes = ["NOT_A_ROUTE"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 1.62μs -> 1.92μs (15.9% slower)
    expected = ["NOT_A_ROUTE"]

def test_edge_mixed_found_and_not_found():
    # Test with a mix of valid and invalid route names
    allowed_routes = ["CHAT", "NOT_A_ROUTE", "EMBEDDINGS", "UNKNOWN_ROUTE"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 2.88μs -> 2.40μs (19.7% faster)
    expected = ["chat/completions", "chat/stream", "NOT_A_ROUTE", "embeddings", "embeddings/stream", "UNKNOWN_ROUTE"]

def test_edge_empty_input():
    # Test with an empty allowed_routes list
    allowed_routes = []
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 479ns -> 1.43μs (66.6% slower)
    expected = []

def test_edge_empty_set_and_list():
    # Test with routes mapping to empty set and empty list
    allowed_routes = ["EMPTY_SET", "EMPTY_LIST"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 2.26μs -> 2.04μs (10.9% faster)
    expected = []

def test_edge_duplicate_route_names():
    # Test with duplicate route names
    allowed_routes = ["CHAT", "CHAT", "EMBEDDINGS"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 2.46μs -> 2.11μs (16.7% faster)
    # Each CHAT should expand to two elements, so total 2+2+2=6 elements
    expected = ["chat/completions", "chat/stream", "chat/completions", "chat/stream", "embeddings", "embeddings/stream"]

def test_edge_non_string_route_names():
    # Test with non-string route names (should be handled gracefully)
    allowed_routes = [None, 123, "CHAT"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 2.61μs -> 2.16μs (20.5% faster)
    # None and 123 are not valid keys, so they should be returned as-is
    expected = [None, 123, "chat/completions", "chat/stream"]

def test_edge_route_name_case_sensitivity():
    # Test with correct and incorrect case
    allowed_routes = ["chat", "CHAT"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 1.98μs -> 2.02μs (2.27% slower)
    # "chat" is not a valid key, so returned as-is; "CHAT" expands
    expected = ["chat", "chat/completions", "chat/stream"]

def test_edge_route_name_with_special_characters():
    # Test with route names containing special characters
    allowed_routes = ["CHAT", "EMBEDDINGS!", "@TEXT"]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 2.38μs -> 2.14μs (11.0% faster)
    # Only CHAT expands, others returned as-is
    expected = ["chat/completions", "chat/stream", "EMBEDDINGS!", "@TEXT"]

# 3. Large Scale Test Cases

def test_large_scale_many_routes():
    # Test with a large number of valid and invalid route names
    allowed_routes = ["CHAT"] * 300 + ["EMBEDDINGS"] * 200 + ["NOT_A_ROUTE"] * 100
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 135μs -> 39.0μs (247% faster)
    # Each CHAT expands to 2 elements, EMBEDDINGS to 2, NOT_A_ROUTE to 1
    expected_length = 300 * 2 + 200 * 2 + 100 * 1

def test_large_scale_all_invalid_routes():
    # Test with 500 route names, all invalid
    allowed_routes = [f"INVALID_{i}" for i in range(500)]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 128μs -> 42.8μs (201% faster)

def test_large_scale_all_valid_routes():
    # Test with 250 "CHAT", 250 "EMBEDDINGS"
    allowed_routes = ["CHAT"] * 250 + ["EMBEDDINGS"] * 250
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 113μs -> 32.3μs (251% faster)
    # Each CHAT and EMBEDDINGS expands to 2 elements
    expected_length = 250 * 2 + 250 * 2
    # Check that only valid route names are present
    valid_routes = {"chat/completions", "chat/stream", "embeddings", "embeddings/stream"}

def test_large_scale_mixed_types():
    # Test with a mix of valid, invalid, None, int, and special chars
    allowed_routes = ["CHAT", None, "EMBEDDINGS", 999, "@BAD_ROUTE"] * 100
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 120μs -> 33.8μs (255% faster)

def test_large_scale_empty_routes():
    # Test with many empty set/list routes
    allowed_routes = ["EMPTY_SET"] * 400 + ["EMPTY_LIST"] * 400
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 178μs -> 49.5μs (261% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
from enum import Enum

# imports
import pytest  # used for our unit tests
from litellm.proxy.auth.auth_checks import get_actual_routes


class LiteLLMRoutes(Enum):
    # Route with a set of values
    TEXT = {"route1", "route2"}
    # Route with a list of values
    IMAGE = ["route3", "route4"]
    # Route with a tuple of values
    AUDIO = ("route5", "route6")
    # Route with a single string value
    VIDEO = "route7"
    # Route with an empty set
    EMPTY_SET = set()
    # Route with an empty list
    EMPTY_LIST = []
    # Route with an empty tuple
    EMPTY_TUPLE = ()
    # Route with a None value
    NONE = None
from litellm.proxy.auth.auth_checks import get_actual_routes

# unit tests

# --- Basic Test Cases ---

def test_basic_set_route():
    # Should expand set route to its elements
    codeflash_output = sorted(get_actual_routes(["TEXT"])) # 1.54μs -> 1.72μs (10.3% slower)

def test_basic_list_route():
    # Should expand list route to its elements
    codeflash_output = get_actual_routes(["IMAGE"]) # 1.62μs -> 1.83μs (11.4% slower)

def test_basic_tuple_route():
    # Should expand tuple route to its elements
    codeflash_output = get_actual_routes(["AUDIO"]) # 1.68μs -> 1.81μs (7.61% slower)

def test_basic_string_route():
    # Should expand string route as iterable to its characters (which is probably unintended)
    # But according to the function, it will extend "route7" as ['r','o','u','t','e','7']
    # Let's test for that behavior
    codeflash_output = get_actual_routes(["VIDEO"]) # 1.54μs -> 1.77μs (13.4% slower)

def test_basic_multiple_routes():
    # Should expand multiple types in order
    codeflash_output = get_actual_routes(["TEXT", "IMAGE", "AUDIO"]); result = codeflash_output # 2.40μs -> 2.05μs (17.1% faster)

def test_basic_mixed_known_and_unknown():
    # Should include unknown route as-is
    codeflash_output = get_actual_routes(["TEXT", "UNKNOWN"]); result = codeflash_output # 2.13μs -> 1.89μs (12.8% faster)

# --- Edge Test Cases ---

def test_empty_allowed_routes():
    # Should return empty list for empty input
    codeflash_output = get_actual_routes([]) # 471ns -> 1.39μs (66.0% slower)

def test_all_unknown_routes():
    # Should return all unknown route names as-is
    codeflash_output = get_actual_routes(["FOO", "BAR"]) # 2.24μs -> 2.04μs (10.2% faster)

def test_some_known_some_unknown():
    # Should expand known and include unknown as-is
    codeflash_output = get_actual_routes(["IMAGE", "FOO"]); result = codeflash_output # 2.04μs -> 1.92μs (6.09% faster)

def test_empty_set_route():
    # Should expand empty set to nothing
    codeflash_output = get_actual_routes(["EMPTY_SET"]) # 1.54μs -> 1.76μs (12.5% slower)

def test_empty_list_route():
    # Should expand empty list to nothing
    codeflash_output = get_actual_routes(["EMPTY_LIST"]) # 1.50μs -> 1.75μs (14.4% slower)

def test_empty_tuple_route():
    # Should expand empty tuple to nothing
    codeflash_output = get_actual_routes(["EMPTY_TUPLE"]) # 1.52μs -> 1.73μs (11.7% slower)


def test_route_with_non_iterable_value():
    # Add a route with an int value to simulate a non-iterable
    class LiteLLMRoutesWithInt(Enum):
        INTVAL = 123
    def get_actual_routes_with_int(allowed_routes: list) -> list:
        actual_routes: list = []
        for route_name in allowed_routes:
            try:
                route_value = LiteLLMRoutesWithInt[route_name].value
                if isinstance(route_value, set):
                    actual_routes.extend(list(route_value))
                else:
                    actual_routes.extend(route_value)
            except KeyError:
                actual_routes.append(route_name)
        return actual_routes
    # Should raise TypeError when trying to extend int
    with pytest.raises(TypeError):
        get_actual_routes_with_int(["INTVAL"])

def test_duplicate_route_names():
    # Should expand each occurrence separately
    codeflash_output = get_actual_routes(["TEXT", "TEXT"]); result = codeflash_output # 2.73μs -> 2.60μs (4.92% faster)

def test_case_sensitivity():
    # Should treat route names case-sensitively
    codeflash_output = get_actual_routes(["text"]) # 1.71μs -> 1.97μs (13.0% slower)

# --- Large Scale Test Cases ---

def test_large_number_of_known_routes():
    # Create a large enum for this test
    class LargeEnum(Enum):
        ROUTE0 = ["a", "b"]
        ROUTE1 = ["c", "d"]
        ROUTE2 = ["e", "f"]
        ROUTE3 = ["g", "h"]
        ROUTE4 = ["i", "j"]
        ROUTE5 = ["k", "l"]
        ROUTE6 = ["m", "n"]
        ROUTE7 = ["o", "p"]
        ROUTE8 = ["q", "r"]
        ROUTE9 = ["s", "t"]
    def get_actual_routes_large(allowed_routes: list) -> list:
        actual_routes: list = []
        for route_name in allowed_routes:
            try:
                route_value = LargeEnum[route_name].value
                if isinstance(route_value, set):
                    actual_routes.extend(list(route_value))
                else:
                    actual_routes.extend(route_value)
            except KeyError:
                actual_routes.append(route_name)
        return actual_routes
    # Build a long list of route names
    allowed_routes = ["ROUTE{}".format(i) for i in range(10)]
    result = get_actual_routes_large(allowed_routes)

def test_large_number_of_unknown_routes():
    # Should return all unknown route names as-is
    allowed_routes = [f"UNKNOWN{i}" for i in range(1000)]
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 254μs -> 83.1μs (207% faster)

def test_large_mixed_known_and_unknown():
    # Mix known and unknown routes
    allowed_routes = ["TEXT"] * 500 + ["UNKNOWN"] * 500
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 223μs -> 60.9μs (267% faster)

def test_performance_large_scale():
    # Should not take excessive time for 1000 elements
    import time
    allowed_routes = ["IMAGE"] * 1000
    start = time.time()
    codeflash_output = get_actual_routes(allowed_routes); result = codeflash_output # 220μs -> 61.2μs (260% faster)
    duration = time.time() - start
# 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_actual_routes-mhwuwo3c and push.

Codeflash Static Badge

The optimized code achieves a **213% speedup** by eliminating expensive exception handling and reducing method lookup overhead in the core loop.

**Key Performance Optimizations:**

1. **Replaced try/except with dictionary lookup**: The original code used `LiteLLMRoutes[route_name]` which throws `KeyError` for invalid routes, requiring expensive exception handling. The optimized version uses `LiteLLMRoutes.__members__.get(route_name)` which returns `None` for missing keys without exceptions. Exception handling in Python is significantly more costly than dictionary lookups.

2. **Cached method references**: The optimized code caches `actual_routes.extend` and `actual_routes.append` as local variables (`extend_actual_routes`, `append_actual_routes`). This eliminates repeated attribute lookups in the loop, which is especially beneficial for the large-scale test cases.

3. **Simplified value handling**: Removed the unnecessary `list()` conversion for sets since `extend()` accepts any iterable, including sets directly.

**Performance Impact Analysis:**
The function is called in authentication flows (as shown in `handle_jwt.py`), where route access permissions are validated. The optimization is particularly effective for:

- **Large-scale scenarios**: Test cases with 500-1000 route names show 200-267% speedups, indicating this function may handle bulk route validation
- **Mixed valid/invalid routes**: 19-20% improvements for realistic mixed scenarios where some route names don't exist in the enum
- **High-frequency calls**: Given its use in auth checks, this function likely executes frequently in production workloads

The optimizations maintain identical behavior and output while dramatically reducing CPU overhead, especially beneficial when validating admin route permissions in authentication-heavy applications.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 November 13, 2025 03:15
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash labels Nov 13, 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: Medium Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant