-
Notifications
You must be signed in to change notification settings - Fork 122
Add generic perf Instrument #979
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
Conversation
|
This is too opaque. Configuring this for someone unfamiliar would be a nightmare. Rather than having a single "command" map, parameters should be exposed individually, validated, and populated with sensible defaults whenever possible. As a rule of thumb -- I should be able to run |
|
You're right, this was written while making the assumption that the user would know how to use The difficulty with replicating About the defaults, I really like In the end, if the issue is with |
Yes, I would not suggests trying to handle everything in But the pass-though configuration really should be treated as a fall back, not as the intended primary was of using the instrument in the "common case".
Yes, that's pretty much how |
That's feasible ... and would make everyone happy. So this means effectively merging the current implementation of the instrument (from This approach could then also allow backward compatibility (instead of what I'm doing right now) and is very easy to integrate as the constructor could simply build a |
|
Yes, that's the sort of thing I had in mind! |
9c28d74 to
55b0e5d
Compare
Introduce an implementation of the PerfInstrument that is more generic than the previous one and which is expected to be able to handle all potential calls to perf (irrespective of the subcommand, flags, options or arguments being used) but which maintains backward compatibility with the previous implementation, targeting perf-stat.
Add tests with parser inputs (i.e. perf stat stdout outputs) and parser outputs (i.e. arrays of WA metrics) for the `perf stat` parser of PerfInstrument. This will be useful when modifying the code of the parser, to verify its robustness. NB: These tests are not exhaustive.
| def setup(self, context): | ||
| self.collector.reset() | ||
| version = self.collector.execute('--version').strip() | ||
| context.update_metadata('versions', self.name, version) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope this is being logged in the right "metadata".
I've noticed the following (optional) idea that hasn't been addressed (from the original post):
The force_install flag is kept from the previous implementation. However, what is the "standard WA way" of providing the perf binary? We could write the path in the agenda (e.g. for comparing versions of perf), we could have a collection of perf binaries in a standard location and pick the ideal one (e.g. based on kernel version of the target) from within the WA perf instrument, we could (but this requires automating the automation, WA, and feels messy) have WA get the binary from a standard location on the host and overwrite that one between runs... Ideally, it would be useful to have both control of which binaries are being used and automation for finding the optimal version (as I believe the perf-kernel interface evolves with the kernel).
Based on ARM-software/devlib#395 and ARM-software/devlib#396, this may be useful but might be complicated to implement(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is the correct metadata.
WA has a standard mechanism for "resource resolution" that allows providing alternative versions of resources via various means.
See how dhrystone workload obtains its executable for example:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But dhrystone is picking its binaries based on the ABI which is pretty easy to check with an ELF reader; what I was considering was to get the version of perf which (AFAIK) can only be obtained by running the binaries themselves ... which requires something able to run them. Another approach would require storing this information in the file system (e.g. in the name).
Let's drop this idea due to its complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But dhrystone is picking its binaries based on the ABI which is pretty easy to check with an ELF reader;
Actually, it's picking the binary based on an arbitrary string, which happens to be the ABI -- we're not checking the ELF header, just resolving based on directory structure. So the same can be done for perf (it's basically what you're saying about encoding in the name, except we use directories rather than modifying the file name).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, my bad for not looking further through the call stack of the code you shared!
I believe this is a good idea. However, this feature isn't required for using perf as a single version is enough in almost all cases. As users of WA-perf seem to have been satisfied with the single version approach until now, let's keep this feature for a potential future PR, once we are certain it will be necessary and used!
wa/instruments/perf.py
Outdated
| A (name, value) tuple for the matched counter (value is 0 if an | ||
| error occurred). | ||
| """ | ||
| name = f'{classifiers["label"]}_{match["name"]}'.replace(' ', '_') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per earlier discussion, we'd like to continue supporting Python 3.5 for the foreseeable future in order to avoid forcing potentially painful migrations on existing WA users. Because of that, 3.6 features, such as format strings, should not be used in WA code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure what the conclusion of ARM-software/devlib#389 was; I have changed the f-strings to format calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that discussion kinda petered out without a concrete conclusion. However, I assume that earlier issue regarding support for Ubuntu 16.04 stands, and since there is nothing essential in 3.6, we're going to stick with 3.5 for the next release, at least.
wa/instruments/perf.py
Outdated
| the comment while ``'comment_units'`` holds the rest of the comment | ||
| (typically the units). Only available for the events for which | ||
| ``perf`` added a comment. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we get this documentation to render to HTML? Appending it to the class docstring doesn't really feel right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put this in the description class attribute of the plugin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
marcbonnici
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently if an error occurs with the perf command, for example a misspelt event, then no error is displayed to the user and instead relies on examining the results / the raw output from perf to see what went wrong. Some form of error checking should be added to alert the user if there was a problem during the invocation of perf.
wa/instruments/perf.py
Outdated
| 'PerfInstrument', | ||
| ] | ||
|
|
||
| DEFAULT_EVENTS = ['migration', 'cs'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration default event should be migrations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
I've added logging of the artefacts extracted from the device. |
|
Due to the complexity of this implementation and the resulting instability of the solution I have experienced, combined with the difficulties of integrating it with the WA framework, this PR will be closed in favour of an upcoming one, built on top of the Python scripts provided for |
Introduction
As discussed in #971, this PR tries to modify the
perfinstrument so that it accepts anyperfcommand. It is related with ARM-software/devlib#388 which implements its back-end. It also requires ARM-software/devlib#387 to properly run someperfsubcommands (ARM-software/devlib#386).The idea is to accept a YAML input (part of the agenda) that is in the format of what
perfexpects:Which then only requires formatting this command based on the input and doesn't require having logic in the WA instrument to handle every
COMMAND.Single Command
An excerpt from an agenda describing a command (here,
perf record) would look like:the accepted keys (
command,flags,kwflags, ...) being the names of the parameters todevlib.utils.cli.Command.__init__(see the back-end implementation). This allows the highest level of flexibility, will support any version ofperfand anyperfsubcommand, is relatively simple to implement and maintain and relatively robust (see the following discussion about fail cases). Having such a level of control over the parts of theperfcommand allows us to take full advantage of YAML anchors. The readability (as seen from the agenda) of this approach partially comes from the expressiveness of theperfflags. As an example, notice thatevents are passed as clearly as in the previous implementation, yet no specific logic had to be implemented for it in the instrument.Full Run
On top of this, the proposed
perfinstrument takes 3 dictionaries of commands (pre_commands,commands,post_commands) based on when these commands have to be run: instead of hardcoding this information in the instrument for each subcommand (cfr. #971), we let the user input it, which is a small amount of low-risk work for them. The keys of the command dictionaries are their labels (as introduced by the previous implementation, see further discussion in the back-end PR).For example, a full agenda:
which will run the following on the device (notice the properly escaped
--field-separator):according to the following rules:
flagsare prepended with-or--based on their length;kwflagsare CSV lists linked with=(valid for allperfcommands; seems to be a (sometimes implicit) standard for flags taking values. This is probably because they all use the same front-end);argsis recursively parsed as a command, allowing to useperfin its original usage (i.e. by launching a command through it and only capturing that command);stdoutandstderrare used as expected and handle the UNIX&-based pipe redirection (see discussion about file names, labels, and which files which commands can see); extra flags could be considered such asstdinor pipes but I'm wondering how generic we should go, here ...NB: The user (writing the agenda) needs to have access to the file names so that they can use the
-o/-iflags to properly pipe theirrecord/report.The
force_installflag is kept from the previous implementation. However, what is the "standard WA way" of providing theperfbinary? We could write the path in the agenda (e.g. for comparing versions ofperf), we could have a collection ofperfbinaries in a standard location and pick the ideal one (e.g. based on kernel version of the target) from within the WAperfinstrument, we could (but this requires automating the automation, WA, and feels messy) have WA get the binary from a standard location on the host and overwrite that one between runs... Ideally, it would be useful to have both control of which binaries are being used and automation for finding the optimal version (as I believe theperf-kernel interface evolves with the kernel).Parsing of the output into WA metrics hasn't been started yet. I propose to have, in this case, a per-command logic (I don't think there is another way) for the
perfsubcommands that are supported (probablystatandreport). Because of how flexible and variable the output ofperf reportcan be (typically a table or a graph), what would be the expected output in terms of WA metrics? I currently have a parser that generates apandas.DataFramefrom the tabular output ofperf reportbut this seems to be "too different" from the JSON-based outputs WA instrument seem to be using. Feedback required!Full Run (with the power of YAML)
Another agenda, similar to the example mentioned in the docstring of the previous implementation, runs the same
perf staton the big and LITTLE clusters (using YAML anchors; #976):Drawbacks
Obviously, the flexibility of this instrument comes at a cost as this approach won't necessarily fail early:
post_commands,commands,pre_commands,force_install) fail early as usual (through using theParameterclass);command,flags,kwflags, ...) fail relatively early, at instantiation-time ofCommand(almost same behaviour asParameter);flags, keys ofkwflags, format of the final command string) fail late, only once the corresponding command is run on the device.Secondly, because
perfis a tool intended to run another command, this instrument is implemented while making the assumption that the user of the agenda file is allowed by the owner of the target to run arbitrary commands on it. In the case they are not, additional security should be implemented. For example, it is possible to write an agenda running the following destructive performance-investigating command:TODO:
Write a "porting guide" from old-PerfInstrumenttoPerfStatInstrumentDeprecatePerfStatInstrumentstatImplement parsers forreportParameter(..., kind=YamlCommandDescriptor)behaves weirdly and required somewhat hacking the constructorteardown: should we remove everything from the target?force_install