Skip to content

Commit 70d40a2

Browse files
committed
perf: optimize RunState memory with slots and faster list operations
1 parent bfc8c63 commit 70d40a2

2 files changed

Lines changed: 15 additions & 17 deletions

File tree

src/agents/run.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ async def run(
559559
raw_original_input = run_state._original_input
560560
original_input = normalize_resumed_input(raw_original_input)
561561
generated_items = run_state._generated_items
562-
session_items = list(run_state._session_items)
562+
session_items = run_state._session_items[:]
563563
model_responses = run_state._model_responses
564564
# Cast to the correct type since we know this is TContext
565565
context_wrapper = cast(RunContextWrapper[TContext], run_state._context)
@@ -591,7 +591,7 @@ def _with_reasoning_item_id_policy(result: RunResult) -> RunResult:
591591

592592
pending_server_items: list[RunItem] | None = None
593593
input_guardrail_results: list[InputGuardrailResult] = (
594-
list(run_state._input_guardrail_results) if run_state is not None else []
594+
run_state._input_guardrail_results[:] if run_state is not None else []
595595
)
596596
tool_input_guardrail_results: list[ToolInputGuardrailResult] = (
597597
list(getattr(run_state, "_tool_input_guardrail_results", []))
@@ -624,7 +624,7 @@ def _with_reasoning_item_id_policy(result: RunResult) -> RunResult:
624624

625625
if session_persistence_enabled and session_input_items_for_persistence:
626626
# Capture the exact input saved so it can be rewound on conversation lock retries.
627-
last_saved_input_snapshot_for_rewind = list(session_input_items_for_persistence)
627+
last_saved_input_snapshot_for_rewind = session_input_items_for_persistence[:]
628628
await save_result_to_session(
629629
session,
630630
session_input_items_for_persistence,
@@ -797,12 +797,12 @@ def _with_reasoning_item_id_policy(result: RunResult) -> RunResult:
797797
max_turns=max_turns,
798798
)
799799
result._current_turn = current_turn
800-
result._model_input_items = list(generated_items)
800+
result._model_input_items = generated_items[:]
801801
# Keep normalized replay aligned with the model-facing
802802
# continuation whenever session history preserved extra items.
803-
result._replay_from_model_input_items = list(
804-
generated_items
805-
) != list(session_items)
803+
result._replay_from_model_input_items = (
804+
generated_items != session_items
805+
)
806806
if run_state is not None:
807807
result._trace_state = run_state._trace_state
808808
if session_persistence_enabled:
@@ -936,10 +936,8 @@ def _with_reasoning_item_id_policy(result: RunResult) -> RunResult:
936936
max_turns=max_turns,
937937
)
938938
result._current_turn = max_turns
939-
result._model_input_items = list(generated_items)
940-
result._replay_from_model_input_items = list(generated_items) != list(
941-
session_items
942-
)
939+
result._model_input_items = generated_items
940+
result._replay_from_model_input_items = generated_items != session_items
943941
if run_state is not None:
944942
result._trace_state = run_state._trace_state
945943
if session_persistence_enabled and include_in_history:
@@ -1101,13 +1099,13 @@ def _with_reasoning_item_id_policy(result: RunResult) -> RunResult:
11011099
turn_session_items = session_items_for_turn(turn_result)
11021100
session_items.extend(turn_session_items)
11031101
if server_conversation_tracker is not None:
1104-
pending_server_items = list(turn_result.new_step_items)
1102+
pending_server_items = turn_result.new_step_items[:]
11051103
server_conversation_tracker.track_server_items(turn_result.model_response)
11061104

11071105
tool_input_guardrail_results.extend(turn_result.tool_input_guardrail_results)
11081106
tool_output_guardrail_results.extend(turn_result.tool_output_guardrail_results)
11091107

1110-
items_to_save_turn = list(turn_session_items)
1108+
items_to_save_turn = turn_session_items[:]
11111109
if not isinstance(turn_result.next_step, NextStepInterruption):
11121110
# When resuming a turn we have already persisted the tool_call items;
11131111
if (
@@ -1207,9 +1205,9 @@ def _with_reasoning_item_id_policy(result: RunResult) -> RunResult:
12071205
max_turns=max_turns,
12081206
)
12091207
result._current_turn = current_turn
1210-
result._model_input_items = list(generated_items)
1211-
result._replay_from_model_input_items = list(generated_items) != list(
1212-
session_items
1208+
result._model_input_items = generated_items[:]
1209+
result._replay_from_model_input_items = (
1210+
generated_items != session_items
12131211
)
12141212
if run_state is not None:
12151213
result._current_turn_persisted_item_count = (

src/agents/run_state.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
_MISSING_CONTEXT_SENTINEL = object()
136136

137137

138-
@dataclass
138+
@dataclass(slots=True)
139139
class RunState(Generic[TContext, TAgent]):
140140
"""Serializable snapshot of an agent run, including context, usage, and interruptions.
141141

0 commit comments

Comments
 (0)