perf: cache inspect.signature() at decoration time in logged_command and cache decorators #97

Closed
opened 2026-03-20 13:18:14 +00:00 by cal · 1 comment
Owner

Problem

utils/decorators.py calls inspect.signature(func) inside the wrapper function — meaning it runs on every invocation of any @logged_command, @cached_api_call, or @cached_single_item decorated function.

Locations

  • logged_command wrapper, lines 66–72: called on every slash command invocation
  • cached_api_call wrapper, lines 219–221: called on every cache miss
  • cached_single_item wrapper, lines 277–279: called on every cache miss

inspect.signature() introspects function objects, annotations, and code — it's not trivially cheap.

Fix

Compute the signature once at decoration time (in the outer decorator function), then close over the result:

def decorator(func):
    sig = inspect.signature(func)
    param_names = list(sig.parameters.keys())[2:]  # skip self, interaction
    
    @functools.wraps(func)
    async def wrapper(*args, **kwargs):
        # Use pre-computed sig and param_names
        ...
    return wrapper

Impact

LOW-MEDIUM — Every slash command invocation pays this cost. Under high autocomplete activity it compounds.

## Problem `utils/decorators.py` calls `inspect.signature(func)` inside the wrapper function — meaning it runs on **every invocation** of any `@logged_command`, `@cached_api_call`, or `@cached_single_item` decorated function. ### Locations - `logged_command` wrapper, lines 66–72: called on every slash command invocation - `cached_api_call` wrapper, lines 219–221: called on every cache miss - `cached_single_item` wrapper, lines 277–279: called on every cache miss `inspect.signature()` introspects function objects, annotations, and code — it's not trivially cheap. ## Fix Compute the signature once at decoration time (in the outer `decorator` function), then close over the result: ```python def decorator(func): sig = inspect.signature(func) param_names = list(sig.parameters.keys())[2:] # skip self, interaction @functools.wraps(func) async def wrapper(*args, **kwargs): # Use pre-computed sig and param_names ... return wrapper ``` ## Impact **LOW-MEDIUM** — Every slash command invocation pays this cost. Under high autocomplete activity it compounds.
cal added the
ai-working
label 2026-03-20 13:18:42 +00:00
cal removed the
ai-working
label 2026-03-20 13:21:34 +00:00
Claude added the
ai-working
label 2026-03-20 16:31:15 +00:00
Claude added the
status/in-progress
label 2026-03-20 16:32:19 +00:00
Claude removed the
status/in-progress
label 2026-03-20 16:34:05 +00:00
Collaborator

PR #107 opened: #107

Moved inspect.signature(func) from inside wrapper functions to the outer decorator function in all three locations (logged_command, cached_api_call, cached_single_item). The signature is now computed once at decoration time and closed over by the wrapper. wrapper.__signature__ in logged_command also reuses the pre-computed sig instead of calling it a second time. 11/11 decorator tests pass.

PR #107 opened: https://git.manticorum.com/cal/major-domo-v2/pulls/107 Moved `inspect.signature(func)` from inside wrapper functions to the outer `decorator` function in all three locations (`logged_command`, `cached_api_call`, `cached_single_item`). The signature is now computed once at decoration time and closed over by the wrapper. `wrapper.__signature__` in `logged_command` also reuses the pre-computed `sig` instead of calling it a second time. 11/11 decorator tests pass.
Claude added
status/pr-open
ai-pr-opened
and removed
ai-working
labels 2026-03-20 16:34:14 +00:00
cal closed this issue 2026-03-20 17:45:53 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: cal/major-domo-v2#97
No description provided.