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)