Skip to content
This repository has been archived by the owner on Nov 26, 2021. It is now read-only.

[RFC] Systrace's custom events formatting #243

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

derkling
Copy link
Contributor

The Android run-time can inject interesting function profiling events from user-space which unfortunately are not formatted using the key=value pairs required by TRAPpy.

The format string it uses is expected by other tools, e.g. systrace, thus changing the formatting at the source can be much more complex than dealing with in in TRAPpy. Since TRAPpy learnt to parse systrace events, we can try to improve its skills by properly parsing these custom events too.

The basic idea is to add a simple call-back based mechanism which allows a specific parser (i.e. SysTrace ) to reformat a data string into a TRAPpy compliant format before processing it the usual way.

This is an initial prototype which I share to get feedback on the overall approach before going further to develop more complex functionalities. Thus, I've not yet added a test for this feature, however a simple example trace can contain these events:

RenderThread-9568  ( 9546) [006] ...1  3210.844141: tracing_mark_write: B|9546|flush drawing commands
hwuiTask1-9571 ( 9546) [007] ...1  3210.844145: tracing_mark_write: E
hwuiTask1-9571 ( 9546) [007] ...1  3210.844151: tracing_mark_write: B|9546|tessellateAmbientShadow
hwuiTask1-9571 ( 9546) [007] ...1  3210.844159: tracing_mark_write: E
hwuiTask1-9571 ( 9546) [007] ...1  3210.844162: tracing_mark_write: B|9546|tessellateSpotShadow
hwuiTask1-9571 ( 9546) [007] ...1  3210.844182: tracing_mark_write: E

As additional goals, not yet provided by this prototype, it would be nice to:

  1. support the generation and registration on-the-fly of new dataframes from within the callback, which should allow to create separate dataframe for different classes of custom events
  2. make sure the systrace viewer and the TRAPpy generated dataframes are on the same timeline, which will require to play with basetime and windows... but, since this is a more complex task, I would keep this topic for a different PR.

Some run-times (e.g. Android) inject interesting events from user-space
which unfortunately are not formatted using the `key=value` pairs required
by TRAPpy. The format string they use is expected by other tools, e.g. systrace.

Since TRAPpy learnt to parse systrace events, let's prepare the ground for
him to improve its skills. This adds a simple call-back based mechanism which
allows a parser to reformat a data string into a TRAPpy compliant format
before processing it the usual way.

Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
Android injects function profiling envets from using tracing_mark strings
which are not formatted according to the `key=value` pari expected by TRAPpy.
Let's use our `formad_data` callback to give the a proper shape.


Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
This event is not really useful and, so far, it's the only one properly
formatted using `key=value` pairs. Let's ignore it while we find a better
way to synchronize TRAPpy and Systrace viewer times.

Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
Copy link
Contributor

@bjackman bjackman left a comment

Choose a reason for hiding this comment

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

Reformatting into a string and then parsing that string doesn't seem like the cleanest way to achieve this.

Do you think it's possible to instead make start_match more flexible in FTrace.__populate_data, then allow overriding the data_dict generation in Base.generate_parsed_data?

So we would modify FTrace.__populate_data so that data_str can be the raw "B|9546|tessellateSpotShadow" (probably by having something that SysTrace overrides, so we don't change behaviour for regular ftrace). Then instead of converting that to a "key=value" string, parse it directly into {'key': 'value'} dicts at a later stage in the parsing (i.e. an overridden method called from Base.generate_parsed_data).

Would need some investigation but if it's possible do you think that's a cleaner solution?

Edited to add: Just noticed the "overridden method called from Base.generate_parsed_data" I referred to is exactly the generate_data_dict method @joelagnel added in his PR.

match.group('func'), match.group('data'))
return data_str

raise ValueError('Unexpected systrace marker: {}'.format(data_str))
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think it should be an error, anyone could put stuff in tracing_mark_write. Maybe log a warning?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed. Logging a warning would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, that was mainly for me while it's in development to check that with many different traces I'm actually matching all the possible custom events. Will change it to a warning.

match.group('func'), match.group('data'))
return data_str

raise ValueError('Unexpected systrace marker: {}'.format(data_str))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed. Logging a warning would be better.

raise ValueError('Unexpected systrace marker: {}'.format(data_str))
return data_str

SYSTRACE_EVENT = re.compile(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add a comment about what this regular expression does. I know regexes are cool, but really hard to read and get right 😄

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually a sample from the trace here would be good.

Copy link
Collaborator

@sinkap sinkap left a comment

Choose a reason for hiding this comment

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

Yep, generate_data_dict would be the way to go. Also can you add/update test cases for your change?

raise ValueError('Unexpected systrace marker: {}'.format(data_str))
return data_str

SYSTRACE_EVENT = re.compile(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually a sample from the trace here would be good.

@derkling
Copy link
Contributor Author

The approach @bjackman suggested was already briefly discussed with @JaviMerino and @credp, and it actually I think it can make much sense... I just not implemented it to push out what I had so far and trigger the discussion. Especially in view of @joelagnel PR #241 ... we need to avoid overlapping features and I was wondering if what I'm proposing here should be better implemented using client callbacks.

What do you think? Do you think it can still be valuable for the SysTrace parser to support directly this additional parsing logic?

@bjackman
Copy link
Contributor

Still investigating @joelagnel's PR but I think SysTrace should parse it directly.

@sinkap sinkap self-assigned this Apr 26, 2017
@joelagnel
Copy link

joelagnel commented Jun 9, 2017

Sorry for the late review on this.
I agree with the discussed approach of using generate_data_dict from the tracer in question. So probably the tracer should pass this function as a callback to the 'class Base' event objects?

@derkling also yes I think there is overlap with #241 but for slightly different purpose, we should definitely use that mechanism, and I think its also good because it might make support for #241 easier. At the moment I am dedicated to solving this systrace parsing problem because we need it for automated trace analysis so lets work together on this and get it done.

@bjackman
Copy link
Contributor

I agree with the discussed approach of using generate_data_dict from the tracer in question. So probably the tracer should pass this function as a callback to the 'class Base' event objects?

Why a callback? Can't it just be an override?

@sinkap sinkap force-pushed the master branch 3 times, most recently from 6f40d93 to a84dd23 Compare June 14, 2017 21:41
@kdub
Copy link
Contributor

kdub commented Nov 6, 2017

Some examples of a custom parser I wrote recently (#271), if it provides any inspiration.

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

Successfully merging this pull request may close these issues.

5 participants