Skip to content

config: Add "events" key in parse_task_phase_data() #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

douglas-raillard-arm
Copy link

@douglas-raillard-arm douglas-raillard-arm commented Feb 4, 2021

Allow parsing an "events" key for phases with the following format:

    "events": [
	{"run": 1000},
	{"timer": {"ref": "helloworld", "period": 16000}},
	{"run": 9000},
	{"sleep": 1000}
    ]

This allows:

  • Enforced ordering of events. Relying on the order of keys in an
    object is issue-prone, as interfaces to interact with mappings in
    most languages are not designed around preserving such order. On
    the contrary, array operations have always a well defined
    order semantic.

  • More critically, this allows repeating the same event an
    arbitrary number of times. Complex workload might otherwise need
    to be split among different phases to workaround that issue, which
    comes with some overhead and extra bookeeping in external code.

Checked constraints:

  • only event objects are allowed in the array
  • objects can only have one key
  • when "events" is in use, no event key is allowed in the phase
    body. This means the user either uses the old format or the new
    one but mixing is not allowed.

Signed-off-by: Douglas RAILLARD [email protected]

@douglas-raillard-arm douglas-raillard-arm force-pushed the events-phase-key branch 3 times, most recently from d3c54a4 to 31f57fb Compare February 4, 2021 17:32
Allow parsing an "events" key for phases with the following format:

    "events": [
	{"run": 1000},
	{"timer": {"ref": "helloworld", "period": 16000}},
	{"run": 9000},
	{"sleep": 1000}
    ]

This allows:
    * Enforced ordering of events. Relying on the order of keys in an
      object is issue-prone, as interfaces to interact with mappings in
      most languages are not designed around preserving such order. On
      the contrary, array operations have always a well defined
      order semantic.

    * More critically, this  allows repeating the same event an
      arbitrary number of times. Complex workload might otherwise need
      to be split among different phases to workaround that issue, which
      comes with some overhead and extra bookeeping in external code.

Checked constraints:
    * only event objects are allowed in the array
    * objects can only have one key
    * when "events" is in use, no event key is allowed in the phase
      body. This means the user either uses the old format or the new
      one but mixing is not allowed.

Signed-off-by: Douglas RAILLARD <[email protected]>

Each object in the array must contain a single event key. This format allows
specifying the same event more than once (like "run" in the example), and is
friendlier to languages with map types that are not preserving insertion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also the case with current mode if you read the beg of the file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean via workgen or the way rt-app handles things currently ?

@@ -650,7 +674,7 @@ The generated events are of these main categories:

- rtapp_loop: event=start thread_loop=0 phase=0 phase_loop=0
- rtapp_loop: event=end thread_loop=0 phase=0 phase_loop=0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't mix typo and new feature in the same patch or PR

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah looks like my text editor stripped the lines, sorry about that

@@ -756,5 +780,3 @@ below)
20000 ++--+----+---+----+---+---+----+---+----+--++ 494000
17560556057560556057560656065606756065606756075607
Loop start time [msec]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto


log_info(PFX "Parsing phase");

data->nbevents = 0;
data->events = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need this ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data->events=NULL is probably an artifact from before I introduced events_array variable, it's indeed not necessary anymore


log_info(PFX "Parsing phase");

data->nbevents = 0;
data->events = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try to not move code unnecessarily

foreach(obj, entry, key, val, idx) {
if (obj_is_event(key))
if(!strncmp("events", key, 6)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this code seems overly complicated and transforms a simple straight forward function in something really complex.; From 2 foreach, it now needs 5 foreach/for loops

events_obj = get_in_object(obj, "events", TRUE); will say you if there is an events array or not

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I was looking for a function like that in json-c but it turns out it's a helper in that file.

foreach(obj, entry, key, val, idx) {
if (obj_is_event(key)) {
/* Check that we are not trying to mix old and new styles */
if (events_array) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if an events array is detected we should simply ignore old style

Copy link
Author

@douglas-raillard-arm douglas-raillard-arm Mar 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really an improvement though ? The foreach is still needed to count the number of events anyway and silently ignoring events is not really something users would thank us for.

EDIT: count the number of old-style event*

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but when we have found an array we can skip this counting entirely because we don't care about old style events

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that this code cannot be removed, if someone is using old-style, this foreach needs to be somewhere. Silently ignoring part of the configuration file in order to save one iteration over a map that has a few tens of keys at most does not sound like a good deal. Even more considered the fact that in well-formed JSON files, the number of keys is bounded by the number of settings, so the only ones "paying a performance cost" are people writing a conf file that is ambiguous and will result in an error. (bearing in mind, we are parsing a configuration file, ahead of time of execution, in C, with an order of magnitude of a few tens or hundreds of keys in extreme cases).

On top of that, this can allow in the future to reclaim some event names for some settings. This sounds a bit crazy given that they have "verb" names for the most part, but the current syntax is lenient: we only match the prefix. This means that something like "synchronous-io" key is currently impossible to add, but would be possible with the "events" array as long as we forbid events outside of it when in use.

for (i=0; i < data->nbevents; i++) {
array_val = json_object_array_get_idx(events_array, i);
is_first_entry = true;
foreach(array_val, entry, key, val, idx) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of this foreach ?
isn't all object inside the array an event

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array items are themselves objects:

[{event1: param1}, {event2: param2}, ...]

The alternative would be to use sub-arrays like a tuple instead of objects, but the object approach is the standard way of doing things, as it is pretty clean in YAML:

events:
    - run: 42
    - sleep: 53

(and the sub-array solution does not save any typing anyway)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but that was already the case with the old style and obj_is_event() is there to check that those objects are events

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After checking parse_task_event_data() it looks like it's doing a validation on the event name and will exit if it's given a non-event so we can skip this check here.

We still need to check the number of keys though, as:

  • 0 keys would mean that the length of the array (and therefore the size of data->events) does not match the actual number of events

  • more than one key does not make sense (at least for now, maybe one day this could be used to attach some sort of metadata to the event)

I need to fix the code to check we are not in the 0 keys situation, currently it would trigger a UB with data->events[i] not being initialized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants