Skip to content

Async wlgen API (2)

Example taken from lisa.wlgen.rta doc:


from lisa.wlgen.rta import RTA, RTAPhase, PeriodicWload, RunWload, SleepWload, override, delete, WithProperties, task_factory, RTAConf
from lisa.fuzz import Float, Int
from lisa.platforms.platinfo import PlatformInfo
from lisa.target import Target

# Alternatively, an async API is available to define tasks.
# Each workload awaited will become a new phase, and WithProperties async
# context manager can be used to set properties for multiple such phases.
#
# Additionally, the random data generators from lisa.fuzz can be used as well.

@task_factory
async def make_task(run_duration):
    async with WithProperties(name='first', uclamp=(256, 512)):
        await RunWload(run_duration)

    # Create a bounded random value
    sleep_duration = await Float(min_=1, max_=5)
    sleep_duration = round(sleep_duration, 2)

    async with WithProperties(name='second'):
        # We could await once on each workload, but that would lead to 2 phases
        # instead of one. Whether this is desired or an issue depends on the
        # use-case.
        await (
            SleepWload(sleep_duration) +
            PeriodicWload(
                duty_cycle_pct=20,
                period=16e-3,
                duration=2,
            )
        )

# "seed" is used to initialize the random number generator. If not
# provided, the seed will be random.
task = make_task(run_duration=1)(seed=1)

# Important note: all the classes in this module are immutable. Modifying
# attributes is not allowed, use the RTAPhase.with_props() if you want to
# get a new object with updated properties.

# You can create a modified RTAPhase using with_props(), and the property
# will be combined with the existing ones.
# For util clamp, it means taking the toughest restrictions, which in this
# case are (300, 512).
task = task.with_props(uclamp=(300, 800))

# If you want to set the clamp and override any existing value rather than
# combining it, you can use the override() function
task = task.with_props(uclamp=override((400, 700)))

# Similarly, you can delete any property that was already set with delete()
task = task.with_props(uclamp=delete())


###################################################
# Alternative 1: create a simple profile and run it
###################################################

# Connect to a target
target = Target.from_default_conf()

# Mapping of rt-app task names to the phases they will execute
profile = {'task1': task}

# Create the RTA object that configures the profile for the given target
wload = RTA.from_profile(target, profile=profile)

# Workloads are context managers to do some cleanup on exit
with wload:
    wload.run()


###################################################
# Alternative 2: a more complex example generating multiple tasks and dumping a JSON.
###################################################

@task_factory
async def make_profile(plat_info, **kwargs):
    nr_tasks = await Int(1, plat_info['cpus-count'])

    profile = {}
    for i in range(nr_tasks):
        async with WithProperties(name=f'task{i}'):
            profile[f'task{i}'] = await make_task(**kwargs)

    # If we return anything else than None, the return value will not be
    # replaced by the phase defined in the function.
    return profile


plat_info = PlatformInfo.from_yaml_map('./doc/traces/plat_info.yml')

# Display a few randomly generated tasks
for _ in range(2):
    # When called, profile_gen() will create a random profiles
    profile_gen = make_profile(plat_info, run_duration=1)

    # seed (or rng) can be fixed for reproducible results
    # profile = profile_gen(seed=1)
    profile = profile_gen(seed=None)

    conf = RTAConf.from_profile(profile, plat_info=plat_info)
    print(conf.json)

Merge request reports