Skip to content

Commit 78a0258

Browse files
committed
Tests and fixes for WorkerProcess and supporting changes
1 parent 8c70303 commit 78a0258

25 files changed

+1424
-1093
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ ignore_missing_imports=true
141141

142142

143143
[tool.ruff]
144+
target-version = "py39"
144145
line-length = 88
145146
indent-width = 4
146147
exclude = ["build", "dist", "env", ".venv"]

src/guidellm/backend/interface.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,19 @@
33
from typing import (
44
Any,
55
Generic,
6-
Literal,
76
Optional,
87
TypeVar,
98
)
109

11-
from pydantic import Field
12-
13-
from guidellm.objects import StandardBaseModel
1410
from guidellm.scheduler import (
11+
MeasuredRequestTimingsT,
1512
RequestT,
16-
RequestTimingsT,
1713
ResponseT,
1814
ScheduledRequestInfo,
1915
)
2016

2117

22-
class BackendInterface(ABC, Generic[RequestT, RequestTimingsT, ResponseT]):
18+
class BackendInterface(ABC, Generic[RequestT, MeasuredRequestTimingsT, ResponseT]):
2319
"""
2420
Abstract interface for request processing backends. Note: before process_startup
2521
is invoked, the implementation must ensure all properties are pickleable.
@@ -71,9 +67,9 @@ async def process_shutdown(self) -> None:
7167
async def resolve(
7268
self,
7369
request: RequestT,
74-
request_info: ScheduledRequestInfo[RequestTimingsT],
70+
request_info: ScheduledRequestInfo[MeasuredRequestTimingsT],
7571
history: Optional[list[tuple[RequestT, ResponseT]]] = None,
76-
) -> AsyncIterator[tuple[ResponseT, ScheduledRequestInfo[RequestTimingsT]]]:
72+
) -> AsyncIterator[tuple[ResponseT, ScheduledRequestInfo[MeasuredRequestTimingsT]]]:
7773
"""
7874
Process a request and yield incremental response updates.
7975

src/guidellm/backend/objects.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from pydantic import Field
1313

1414
from guidellm.objects.pydantic import StandardBaseModel
15-
from guidellm.scheduler import RequestTimings
15+
from guidellm.scheduler import MeasuredRequestTimings
1616

1717
__all__ = [
1818
"GenerationRequest",
@@ -135,7 +135,7 @@ def preferred_output_tokens(
135135
return self.response_output_tokens or self.request_output_tokens
136136

137137

138-
class GenerationRequestTimings(RequestTimings):
138+
class GenerationRequestTimings(MeasuredRequestTimings):
139139
"""Timing model for tracking generation request lifecycle events."""
140140

141141
first_iteration: Optional[float] = Field(

src/guidellm/benchmark/aggregator.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
StatusDistributionSummary,
5050
)
5151
from guidellm.scheduler import (
52+
MeasuredRequestTimingsT,
5253
RequestT,
53-
RequestTimingsT,
5454
ResponseT,
5555
ScheduledRequestInfo,
5656
SchedulerState,
@@ -67,7 +67,7 @@
6767

6868

6969
@runtime_checkable
70-
class Aggregator(Protocol[ResponseT, RequestT, RequestTimingsT]):
70+
class Aggregator(Protocol[ResponseT, RequestT, MeasuredRequestTimingsT]):
7171
"""
7272
Protocol for processing benchmark data updates during execution.
7373
@@ -81,7 +81,7 @@ def __call__(
8181
agg_state: dict[str, Any],
8282
response: Optional[ResponseT],
8383
request: RequestT,
84-
request_info: ScheduledRequestInfo[RequestTimingsT],
84+
request_info: ScheduledRequestInfo[MeasuredRequestTimingsT],
8585
scheduler_state: SchedulerState,
8686
) -> Optional[dict[str, Any]]:
8787
"""
@@ -98,7 +98,7 @@ def __call__(
9898

9999

100100
@runtime_checkable
101-
class CompilableAggregator(Aggregator[ResponseT, RequestT, RequestTimingsT]):
101+
class CompilableAggregator(Aggregator[ResponseT, RequestT, MeasuredRequestTimingsT]):
102102
"""
103103
Protocol for aggregators that compile final results from aggregated state.
104104
@@ -146,7 +146,7 @@ def add_aggregate_metric(
146146

147147

148148
class SchedulerStatsAggregator(
149-
CompilableAggregator[ResponseT, RequestT, RequestTimingsT]
149+
CompilableAggregator[ResponseT, RequestT, MeasuredRequestTimingsT]
150150
):
151151
"""
152152
Aggregates scheduler timing and performance metrics.
@@ -160,7 +160,7 @@ def __call__(
160160
agg_state: dict[str, Any],
161161
response: Optional[ResponseT],
162162
request: RequestT,
163-
request_info: ScheduledRequestInfo[RequestTimingsT],
163+
request_info: ScheduledRequestInfo[MeasuredRequestTimingsT],
164164
scheduler_state: SchedulerState,
165165
) -> Optional[dict[str, Any]]:
166166
"""

src/guidellm/benchmark/benchmarker.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
BackendT,
3333
Constraint,
3434
Environment,
35+
MeasuredRequestTimingsT,
3536
RequestT,
36-
RequestTimingsT,
3737
ResponseT,
3838
Scheduler,
3939
SchedulerState,
@@ -45,7 +45,7 @@
4545

4646

4747
class Benchmarker(
48-
Generic[BenchmarkT, RequestT, RequestTimingsT, ResponseT],
48+
Generic[BenchmarkT, RequestT, MeasuredRequestTimingsT, ResponseT],
4949
ABC,
5050
ThreadSafeSingletonMixin,
5151
):
@@ -65,14 +65,14 @@ async def run(
6565
requests: Iterable[
6666
Union[RequestT, Iterable[Union[RequestT, tuple[RequestT, float]]]]
6767
],
68-
backend: BackendT[RequestT, RequestTimingsT, ResponseT],
68+
backend: BackendT[RequestT, MeasuredRequestTimingsT, ResponseT],
6969
profile: Profile,
7070
environment: Environment,
7171
benchmark_aggregators: dict[
7272
str,
7373
Union[
74-
Aggregator[ResponseT, RequestT, RequestTimingsT],
75-
CompilableAggregator[ResponseT, RequestT, RequestTimingsT],
74+
Aggregator[ResponseT, RequestT, MeasuredRequestTimingsT],
75+
CompilableAggregator[ResponseT, RequestT, MeasuredRequestTimingsT],
7676
],
7777
],
7878
benchmark_class: type[BenchmarkT],
@@ -114,7 +114,9 @@ async def run(
114114
request,
115115
request_info,
116116
scheduler_state,
117-
) in Scheduler[BackendT, RequestT, RequestTimingsT, ResponseT].run(
117+
) in Scheduler[
118+
BackendT, RequestT, MeasuredRequestTimingsT, ResponseT
119+
].run(
118120
requests=requests,
119121
backend=backend,
120122
strategy=strategy,
@@ -161,13 +163,13 @@ def _compile_benchmark_kwargs(
161163
requests: Iterable[
162164
Union[RequestT, Iterable[Union[RequestT, tuple[RequestT, float]]]]
163165
],
164-
backend: BackendT[RequestT, RequestTimingsT, ResponseT],
166+
backend: BackendT[RequestT, MeasuredRequestTimingsT, ResponseT],
165167
environment: Environment,
166168
aggregators: dict[
167169
str,
168170
Union[
169-
Aggregator[ResponseT, RequestT, RequestTimingsT],
170-
CompilableAggregator[ResponseT, RequestT, RequestTimingsT],
171+
Aggregator[ResponseT, RequestT, MeasuredRequestTimingsT],
172+
CompilableAggregator[ResponseT, RequestT, MeasuredRequestTimingsT],
171173
],
172174
],
173175
aggregators_state: dict[str, dict[str, Any]],

src/guidellm/scheduler/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
from .objects import (
1818
BackendInterface,
1919
BackendT,
20+
MeasuredRequestTimings,
21+
MeasuredRequestTimingsT,
2022
RequestSchedulerTimings,
2123
RequestT,
22-
RequestTimings,
23-
RequestTimingsT,
2424
ResponseT,
2525
ScheduledRequestInfo,
2626
SchedulerState,
@@ -68,13 +68,13 @@
6868
"MaxGlobalErrorRateConstraintInitializer",
6969
"MaxNumberConstraint",
7070
"MaxNumberConstraintInitializer",
71+
"MeasuredRequestTimings",
72+
"MeasuredRequestTimingsT",
7173
"NoDelayRequestTimings",
7274
"NonDistributedEnvironment",
7375
"PoissonRateRequestTimings",
7476
"RequestSchedulerTimings",
7577
"RequestT",
76-
"RequestTimings",
77-
"RequestTimingsT",
7878
"ResponseT",
7979
"ScheduledRequestInfo",
8080
"ScheduledRequestTimings",

src/guidellm/scheduler/constraints.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,11 @@ def create(cls, key: str, *args, **kwargs) -> ConstraintInitializer:
101101
initializer_class = cls.get_registered_object(key)
102102

103103
# Handle simple scalar values by delegating to the initializer class
104-
if (len(args) == 1 and not kwargs and
105-
hasattr(initializer_class, "from_simple_value")):
104+
if (
105+
len(args) == 1
106+
and not kwargs
107+
and hasattr(initializer_class, "from_simple_value")
108+
):
106109
return initializer_class.from_simple_value(args[0])
107110

108111
return initializer_class(*args, **kwargs)

src/guidellm/scheduler/environment.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
from guidellm.config import settings
2222
from guidellm.scheduler.constraints import Constraint
2323
from guidellm.scheduler.objects import (
24+
MeasuredRequestTimingsT,
2425
RequestT,
25-
RequestTimingsT,
2626
ResponseT,
2727
ScheduledRequestInfo,
2828
SchedulerState,
@@ -84,7 +84,7 @@ async def update_run_iteration(
8484
self,
8585
response: Optional[ResponseT],
8686
request: RequestT,
87-
request_info: ScheduledRequestInfo[RequestTimingsT],
87+
request_info: ScheduledRequestInfo[MeasuredRequestTimingsT],
8888
):
8989
"""
9090
Update environment state with completed request iteration.
@@ -116,7 +116,10 @@ async def sync_run_end(
116116
self,
117117
) -> AsyncIterator[
118118
tuple[
119-
ResponseT, RequestT, ScheduledRequestInfo[RequestTimingsT], SchedulerState
119+
ResponseT,
120+
RequestT,
121+
ScheduledRequestInfo[MeasuredRequestTimingsT],
122+
SchedulerState,
120123
]
121124
]:
122125
"""
@@ -176,7 +179,7 @@ async def update_run_iteration(
176179
self,
177180
response: Optional[ResponseT],
178181
request: RequestT,
179-
request_info: ScheduledRequestInfo[RequestTimingsT],
182+
request_info: ScheduledRequestInfo[MeasuredRequestTimingsT],
180183
):
181184
"""
182185
No-op for single-node execution.
@@ -198,7 +201,10 @@ async def sync_run_end(
198201
self,
199202
) -> AsyncIterator[
200203
tuple[
201-
ResponseT, RequestT, ScheduledRequestInfo[RequestTimingsT], SchedulerState
204+
ResponseT,
205+
RequestT,
206+
ScheduledRequestInfo[MeasuredRequestTimingsT],
207+
SchedulerState,
202208
]
203209
]:
204210
"""

src/guidellm/scheduler/objects.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@
2828
Optional,
2929
TypeVar,
3030
)
31-
from typing_extensions import TypedDict
3231

33-
from pydantic import computed_field, Field
32+
from pydantic import Field, computed_field
33+
from typing_extensions import TypedDict
3434

3535
from guidellm.objects import StandardBaseModel
3636

3737
__all__ = [
3838
"BackendInterface",
3939
"BackendT",
40+
"MeasuredRequestTimings",
41+
"MeasuredRequestTimingsT",
4042
"RequestSchedulerTimings",
4143
"RequestT",
42-
"RequestTimings",
43-
"RequestTimingsT",
4444
"ResponseT",
4545
"ScheduledRequestInfo",
4646
"SchedulerState",
@@ -82,7 +82,7 @@ class RequestSchedulerTimings(StandardBaseModel):
8282
)
8383

8484

85-
class RequestTimings(StandardBaseModel):
85+
class MeasuredRequestTimings(StandardBaseModel):
8686
"""Base timing measurements for backend request processing."""
8787

8888
request_start: Optional[float] = Field(
@@ -93,10 +93,12 @@ class RequestTimings(StandardBaseModel):
9393
)
9494

9595

96-
RequestTimingsT = TypeVar("RequestTimingsT", bound=RequestTimings)
96+
MeasuredRequestTimingsT = TypeVar(
97+
"MeasuredRequestTimingsT", bound=MeasuredRequestTimings
98+
)
9799

98100

99-
class ScheduledRequestInfo(StandardBaseModel, Generic[RequestTimingsT]):
101+
class ScheduledRequestInfo(StandardBaseModel, Generic[MeasuredRequestTimingsT]):
100102
"""Complete request information including status, timings, and metadata."""
101103

102104
request_id: str = Field(description="Unique identifier for the request")
@@ -120,7 +122,7 @@ class ScheduledRequestInfo(StandardBaseModel, Generic[RequestTimingsT]):
120122
default_factory=RequestSchedulerTimings,
121123
description="Scheduler-level timing measurements for request lifecycle",
122124
)
123-
request_timings: Optional[RequestTimingsT] = Field(
125+
request_timings: Optional[MeasuredRequestTimingsT] = Field(
124126
default=None,
125127
description="Backend-specific timing measurements for request processing",
126128
)
@@ -152,7 +154,7 @@ def completed_at(self) -> Optional[float]:
152154
return request_end or self.scheduler_timings.resolve_end
153155

154156

155-
class BackendInterface(ABC, Generic[RequestT, RequestTimingsT, ResponseT]):
157+
class BackendInterface(ABC, Generic[RequestT, MeasuredRequestTimingsT, ResponseT]):
156158
"""
157159
Abstract interface for request processing backends. Note: before process_startup
158160
is invoked, the implementation must ensure all properties are pickleable.
@@ -204,9 +206,9 @@ async def process_shutdown(self) -> None:
204206
async def resolve(
205207
self,
206208
request: RequestT,
207-
request_info: ScheduledRequestInfo[RequestTimingsT],
209+
request_info: ScheduledRequestInfo[MeasuredRequestTimingsT],
208210
history: Optional[list[tuple[RequestT, ResponseT]]] = None,
209-
) -> AsyncIterator[tuple[ResponseT, ScheduledRequestInfo[RequestTimingsT]]]:
211+
) -> AsyncIterator[tuple[ResponseT, ScheduledRequestInfo[MeasuredRequestTimingsT]]]:
210212
"""
211213
Process a request and yield incremental response updates.
212214

0 commit comments

Comments
 (0)