Spracherkennung für: .rst vermutete Sprache: Abap {ABAP[99] VDM[80] VHDL[70]} [Methode: maximale Elemente, drei Dimensionen]
Developing
in mozperftest
=========================
Architecture overview
---------------------
`mozperftest` implements a mach command that
is a thin wrapper
on the
top
of `runner.py`, which allows us
to run the tool without having
to go through
a mach
call. Command arguments are prepared
in `argparser.py`
and then made
available
for the runner.
The runner creates a `MachEnvironment` instance (see `environment.py`)
and a
`Metadata` instance (see `metadata.py`). These two objects are
shared during the
whole test
and used
to share
data across all parts.
The runner then calls `MachEnvironment.
run`, which
is in charge
of running the test.
The `MachEnvironment` instance runs a sequence
of **layers**.
Layers are classes responsible
for one
single aspect
of a performance test. They
are organized
in three categories:
-
**system**: anything that sets up and tears down some resources or services
on the system. Existing system layers:
**android**, **proxy**
-
**test**: layers that are in charge of running a test to collect metrics.
Existing test layers:
**browsertime** and **androidlog**
-
**metrics**: all layers that process the metrics to turn them into usable
metrics. Existing system layers:
**perfherder** and **console**
The MachEnvironment instance collects a series
of layers
for each category
and
runs them sequentially.
The goal
of this organization
is to allow adding new performance tests runners
that will be based
on a specific combination
of layers.
To avoid messy
code,
we need
to make sure that each layer represents a
single aspect
of the process
and that
is completely independent
of other layers (besides sharing the
data
through the common environment.)
For instance, we could use `perftest`
to run a C++ benchmark
by implementing a
new
**test** layer.
Layer
-----
A layer
is a
class that inherits
from `mozperftest.layers.Layer`
and implements
a few
methods and class variables.
List
of methods and variables:
- `name`: name
of the layer (
class variable, mandatory)
- `activated`: boolean
to activate
by default the layer (
class variable, False)
- `user_exception`: will trigger the `on_exception` hook
when an exception
occurs
- `arguments`: dict containing arguments. Each argument
is following
the `argparser`
standard
- `
run(self, metadata)`: called
to execute the layer
- `setup(self)`: called
when the layer
is about
to be executed
- `teardown(self)`: called
when the layer
is exiting
Example::
class EmailSender(Layer):
"""Sends an email with the results.
"""
name =
"email"
activated = False
arguments = {
"recipient": {
"type": str,
"default":
"tarek@mozilla.com",
"help":
"Recipient",
},
}
def setup(self):
self.server = smtplib.SMTP(smtp_server,port)
def teardown(self):
self.server.quit()
def __call__(self, metadata):
self.server.send_email(self.get_arg(
"recipient"), metadata.results())
It can then be added
to one
of the top functions that are used
to create a list
of layers
for each category:
-
**mozperftest.metrics.pick_metrics** for the metrics category
-
**mozperftest.system.pick_system** for the system category
-
**mozperftest.test.pick_browser** for the test category
And also added
in each `get_layers`
function in each
of those categories.
The `get_layers` functions are invoked
when building the argument parser.
In our example, adding the `EmailSender` layer will
add two new options:
-
**--email** a flag to activate the layer
-
**--email-recipient**
Important layers
----------------
**mozperftest** can be used to run performance tests against browsers using the
**browsertime** test layer. It leverages the `browsertime.js
<
https://www.sitespeed.io/documentation/browsertime/>`_ framework
and provides
a full integration
into Mozilla
's build and CI systems.
Browsertime uses the Selenium Webdriver
client to drive the browser,
and
provides some metrics
to measure performance during a user journey.
Coding style
------------
For the coding style, we want
to:
- Follow `PEP
257 <
https://www.python.org/dev/peps/pep-0257/>`_
for docstrings
- Avoid complexity
as much
as possible
- Use modern Python
3 code (
for instance `pathlib` instead
of `os.path`)
- Avoid dependencies
on Mozilla build projects
and frameworks
as much
as possible
(mozharness, mozbuild, etc),
or make sure they are isolated
and documented
Landing patches
---------------
.. warning::
It
is mandatory
for each patch
to have a test.
Any change without a test
will be rejected.
Before landing a patch
for mozperftest, make sure you
run `perftest-test`::
% ./mach perftest-test
=> black [OK]
=> flake8 [OK]
=> remove old coverage
data [OK]
=> running tests [OK]
=> coverage
Name Stmts Miss Cover Missing
--------------------------------------------------------------------------------
----------
mozperftest/metrics/notebook/analyzer.py 29 20 31% 26-36, 39-42, 45-51
...
mozperftest/system/proxy.py 37 0 100%
------------------------------------------------------------------------------------------
TOTAL 1614 240 85%
[OK]
The command will run `black`, `flake8` and also make sure that the test coverage has not regressed.
You can use the `-s` option to bypass flake8/black to speed up your workflow, but make
sure you do a full tests run. You can also pass the name of one single test module.