Skip to content

guidellm.benchmark.profiles.profile

Profile base class for multi-strategy benchmark execution.

Profile

Bases: ABC

Coordinate multi-strategy benchmark execution with automatic strategy generation.

Manages sequential execution of scheduling strategies with automatic strategy generation, constraint management, and completion tracking. Subclasses define specific execution patterns like synchronous, concurrent, throughput-focused, rate-based async, or adaptive sweep profiles.

Example: :: @Profile.register("synchronous") class SynchronousProfile(Profile): def init(self, args: SynchronousProfileArgs): super().init(args)

args = SynchronousProfileArgs(kind="synchronous")
profile = Profile.create(args)
Source code in src/guidellm/benchmark/profiles/profile.py
class Profile(ABC):
    """
    Coordinate multi-strategy benchmark execution with automatic strategy generation.

    Manages sequential execution of scheduling strategies with automatic strategy
    generation, constraint management, and completion tracking. Subclasses define
    specific execution patterns like synchronous, concurrent, throughput-focused,
    rate-based async, or adaptive sweep profiles.

    Example:
    ::
        @Profile.register("synchronous")
        class SynchronousProfile(Profile):
            def __init__(self, args: SynchronousProfileArgs):
                super().__init__(args)

        args = SynchronousProfileArgs(kind="synchronous")
        profile = Profile.create(args)
    """

    def __init__(
        self,
        args: ProfileArgs,
        random_seed: int,
        constraints: MutableMapping[str, ConstraintInitializer | Any] | None,
        **kwargs: Any,
    ):
        """
        Initialize a profile instance.

        :param args: Validated profile argument model for this profile type
        :param random_seed: Seed for reproducible random operations in profile
            strategies.
        :param constraints: Constraints for the profile strategies.
        :param kwargs: Additional profile-specific configuration parameters
        """
        _ = kwargs  # unused
        self.kind = args.kind
        self.args = args
        self.random_seed = random_seed
        self.constraints = dict(constraints or {})
        self.completed_strategies: list[SchedulingStrategy] = []

    @property
    def info(self) -> dict[str, Any]:
        """
        Help json serialization by deferring to ProfileArgs.
        """
        return self.args.model_dump()

    @property
    def strategy_types(self) -> list[str]:
        """
        :return: Strategy types executed or to be executed in this profile
        """
        return [strat.type_ for strat in self.completed_strategies]

    @property
    def conclusion(self) -> dict[str, Any] | None:
        """
        What the profile concluded, available once its run has finished.

        Profiles that answer a question rather than execute a fixed sequence
        override this. It is read after the final strategy completes, which is
        the only point at which such an answer exists: ``info`` is captured
        into each benchmark's config before that benchmark runs, so it can
        never carry the last strategy's contribution.

        :return: Serializable conclusion mapping, or None for profiles that
            only execute a planned sequence
        """
        return None

    @staticmethod
    def _should_stop_escalating(prev_benchmark: Benchmark) -> bool:
        """
        Check if a benchmark was terminated by a constraint with stopping_scope="all".

        Inspects the scheduler state's end_queuing_constraints for any constraint
        whose stopping_scope is "all", indicating the system could not handle the
        load and escalation to subsequent rates/streams should halt.

        :param prev_benchmark: Benchmark instance
        :return: True if escalation should stop, False otherwise
        """
        scheduler_state = getattr(prev_benchmark, "scheduler_state", None)
        if scheduler_state is None:
            return False

        for name, action in scheduler_state.end_queuing_constraints.items():
            if action.stopping_scope == "all":
                logger.debug(
                    "Stopping rate escalation: constraint '{}' "
                    "triggered (stopping_scope=all)",
                    name,
                )
                return True
        return False

    def strategies_generator(
        self,
    ) -> Generator[
        tuple[SchedulingStrategy, dict[str, Constraint] | None],
        Benchmark | None,
        None,
    ]:
        """
        Generate strategies and constraints for sequential execution.

        :return: Generator yielding (strategy, constraints) tuples and receiving
            benchmark results after each execution
        """
        prev_strategy: SchedulingStrategy | None = None
        prev_benchmark: Benchmark | None = None

        while (
            strategy := self.next_strategy(prev_strategy, prev_benchmark)
        ) is not None:
            constraints = self.next_strategy_constraints(
                strategy, prev_strategy, prev_benchmark
            )
            prev_benchmark = yield (
                strategy,
                constraints,
            )
            prev_strategy = strategy
            self.completed_strategies.append(prev_strategy)

    @abstractmethod
    def next_strategy(
        self,
        prev_strategy: SchedulingStrategy | None,
        prev_benchmark: Benchmark | None,
    ) -> SchedulingStrategy | None:
        """
        Generate next strategy in the profile execution sequence.

        :param prev_strategy: Previously completed strategy instance
        :param prev_benchmark: Benchmark results from previous strategy execution
        :return: Next strategy to execute, or None if profile complete
        """
        ...

    def next_strategy_constraints(
        self,
        next_strategy: SchedulingStrategy | None,
        prev_strategy: SchedulingStrategy | None,
        prev_benchmark: Benchmark | None,
    ) -> dict[str, Constraint] | None:
        """
        Generate constraints for next strategy execution.

        :param next_strategy: Strategy to be executed next
        :param prev_strategy: Previously completed strategy instance
        :param prev_benchmark: Benchmark results from previous strategy execution
        :return: Constraints dictionary for next strategy, or None
        """
        _ = (prev_strategy, prev_benchmark)  # unused
        return (
            ConstraintsInitializerFactory.resolve(self.constraints)
            if next_strategy and self.constraints
            else None
        )

conclusion property

What the profile concluded, available once its run has finished.

Profiles that answer a question rather than execute a fixed sequence override this. It is read after the final strategy completes, which is the only point at which such an answer exists: info is captured into each benchmark's config before that benchmark runs, so it can never carry the last strategy's contribution.

Returns:

Type Description
dict[str, Any] | None

Serializable conclusion mapping, or None for profiles that only execute a planned sequence

info property

Help json serialization by deferring to ProfileArgs.

strategy_types property

Returns:

Type Description
list[str]

Strategy types executed or to be executed in this profile

__init__(args, random_seed, constraints, **kwargs)

Initialize a profile instance.

Parameters:

Name Type Description Default
args ProfileArgs

Validated profile argument model for this profile type

required
random_seed int

Seed for reproducible random operations in profile strategies.

required
constraints MutableMapping[str, ConstraintInitializer | Any] | None

Constraints for the profile strategies.

required
kwargs Any

Additional profile-specific configuration parameters

{}
Source code in src/guidellm/benchmark/profiles/profile.py
def __init__(
    self,
    args: ProfileArgs,
    random_seed: int,
    constraints: MutableMapping[str, ConstraintInitializer | Any] | None,
    **kwargs: Any,
):
    """
    Initialize a profile instance.

    :param args: Validated profile argument model for this profile type
    :param random_seed: Seed for reproducible random operations in profile
        strategies.
    :param constraints: Constraints for the profile strategies.
    :param kwargs: Additional profile-specific configuration parameters
    """
    _ = kwargs  # unused
    self.kind = args.kind
    self.args = args
    self.random_seed = random_seed
    self.constraints = dict(constraints or {})
    self.completed_strategies: list[SchedulingStrategy] = []

next_strategy(prev_strategy, prev_benchmark) abstractmethod

Generate next strategy in the profile execution sequence.

Parameters:

Name Type Description Default
prev_strategy SchedulingStrategy | None

Previously completed strategy instance

required
prev_benchmark Benchmark | None

Benchmark results from previous strategy execution

required

Returns:

Type Description
SchedulingStrategy | None

Next strategy to execute, or None if profile complete

Source code in src/guidellm/benchmark/profiles/profile.py
@abstractmethod
def next_strategy(
    self,
    prev_strategy: SchedulingStrategy | None,
    prev_benchmark: Benchmark | None,
) -> SchedulingStrategy | None:
    """
    Generate next strategy in the profile execution sequence.

    :param prev_strategy: Previously completed strategy instance
    :param prev_benchmark: Benchmark results from previous strategy execution
    :return: Next strategy to execute, or None if profile complete
    """
    ...

next_strategy_constraints(next_strategy, prev_strategy, prev_benchmark)

Generate constraints for next strategy execution.

Parameters:

Name Type Description Default
next_strategy SchedulingStrategy | None

Strategy to be executed next

required
prev_strategy SchedulingStrategy | None

Previously completed strategy instance

required
prev_benchmark Benchmark | None

Benchmark results from previous strategy execution

required

Returns:

Type Description
dict[str, Constraint] | None

Constraints dictionary for next strategy, or None

Source code in src/guidellm/benchmark/profiles/profile.py
def next_strategy_constraints(
    self,
    next_strategy: SchedulingStrategy | None,
    prev_strategy: SchedulingStrategy | None,
    prev_benchmark: Benchmark | None,
) -> dict[str, Constraint] | None:
    """
    Generate constraints for next strategy execution.

    :param next_strategy: Strategy to be executed next
    :param prev_strategy: Previously completed strategy instance
    :param prev_benchmark: Benchmark results from previous strategy execution
    :return: Constraints dictionary for next strategy, or None
    """
    _ = (prev_strategy, prev_benchmark)  # unused
    return (
        ConstraintsInitializerFactory.resolve(self.constraints)
        if next_strategy and self.constraints
        else None
    )

strategies_generator()

Generate strategies and constraints for sequential execution.

Returns:

Type Description
Generator[tuple[SchedulingStrategy, dict[str, Constraint] | None], Benchmark | None, None]

Generator yielding (strategy, constraints) tuples and receiving benchmark results after each execution

Source code in src/guidellm/benchmark/profiles/profile.py
def strategies_generator(
    self,
) -> Generator[
    tuple[SchedulingStrategy, dict[str, Constraint] | None],
    Benchmark | None,
    None,
]:
    """
    Generate strategies and constraints for sequential execution.

    :return: Generator yielding (strategy, constraints) tuples and receiving
        benchmark results after each execution
    """
    prev_strategy: SchedulingStrategy | None = None
    prev_benchmark: Benchmark | None = None

    while (
        strategy := self.next_strategy(prev_strategy, prev_benchmark)
    ) is not None:
        constraints = self.next_strategy_constraints(
            strategy, prev_strategy, prev_benchmark
        )
        prev_benchmark = yield (
            strategy,
            constraints,
        )
        prev_strategy = strategy
        self.completed_strategies.append(prev_strategy)

ProfileFactory

Bases: RegistryMixin['type[Profile]']

Source code in src/guidellm/benchmark/profiles/profile.py
class ProfileFactory(RegistryMixin["type[Profile]"]):
    @classmethod
    def create(
        cls,
        args: ProfileArgs,
        random_seed: int,
        constraints: MutableMapping[str, ConstraintInitializer | Any] | None = None,
        **kwargs: Any,
    ) -> Profile:
        """
        Create profile instances from validated profile arguments.

        :param args: Validated profile argument model for the target profile type
        :param random_seed: Seed for reproducible random operations in profile
            strategies.
        :param constraints: Constraints for the profile strategies.
        :param kwargs: Additional profile-specific configuration parameters
        :return: Configured profile instance for the specified type
        :raises ValueError: If the profile kind is not registered
        """
        kind = args.kind

        profile_class = cls.get_registered_object(kind)

        if profile_class is None:
            raise ValueError(
                f"Profile type '{kind}' is not registered. "
                f"Available types: {list(cls.registry.keys()) if cls.registry else []}"
            )

        return profile_class(args, random_seed, constraints, **kwargs)

    @classmethod
    def registered_names(cls) -> tuple[str, ...]:
        """
        Get all registered names from the registry.
        """
        return tuple(cls.registry.keys() if cls.registry else [])

create(args, random_seed, constraints=None, **kwargs) classmethod

Create profile instances from validated profile arguments.

Parameters:

Name Type Description Default
args ProfileArgs

Validated profile argument model for the target profile type

required
random_seed int

Seed for reproducible random operations in profile strategies.

required
constraints MutableMapping[str, ConstraintInitializer | Any] | None

Constraints for the profile strategies.

None
kwargs Any

Additional profile-specific configuration parameters

{}

Returns:

Type Description
Profile

Configured profile instance for the specified type

Raises:

Type Description
ValueError

If the profile kind is not registered

Source code in src/guidellm/benchmark/profiles/profile.py
@classmethod
def create(
    cls,
    args: ProfileArgs,
    random_seed: int,
    constraints: MutableMapping[str, ConstraintInitializer | Any] | None = None,
    **kwargs: Any,
) -> Profile:
    """
    Create profile instances from validated profile arguments.

    :param args: Validated profile argument model for the target profile type
    :param random_seed: Seed for reproducible random operations in profile
        strategies.
    :param constraints: Constraints for the profile strategies.
    :param kwargs: Additional profile-specific configuration parameters
    :return: Configured profile instance for the specified type
    :raises ValueError: If the profile kind is not registered
    """
    kind = args.kind

    profile_class = cls.get_registered_object(kind)

    if profile_class is None:
        raise ValueError(
            f"Profile type '{kind}' is not registered. "
            f"Available types: {list(cls.registry.keys()) if cls.registry else []}"
        )

    return profile_class(args, random_seed, constraints, **kwargs)

registered_names() classmethod

Get all registered names from the registry.

Source code in src/guidellm/benchmark/profiles/profile.py
@classmethod
def registered_names(cls) -> tuple[str, ...]:
    """
    Get all registered names from the registry.
    """
    return tuple(cls.registry.keys() if cls.registry else [])