mozregression – new way for handling merges

I am currently investigating how we can make mozregression smarter to handle merges, and I will explain how in this post.


Problem

While bisecting builds with mozregression on mozilla-central, we often end up with a merge commit. These commits often incorporate many individual changes, consider for example this url for a merge commit. A regression will be hard to find inside such a large range of commits.


How mozregression currently works

Once we reach a one day range by bisecting mozilla-central or a release branch, we keep the most recent commit tested, and we use that for the end of a new range to bisect mozilla-inbound (or another integration branch, depending on the application) The beginning of that mozilla-inbound range is determined by one commit found 4 days preceding the date of the push of the commit (date pushed on mozilla-central) to be sure we won’t miss any commit in mozilla-central.

But there are multiple problems. First, it is not always the case that the offending commit really comes from m-i. It could be from any other integration branch (fx-team, b2g-inbound, etc). Second, bisecting over a 4 days range in mozilla-inbound may involve testing a lot of builds, with some that are useless to test.


Another approach

How can we improve this ? As just stated, there are two points that can be improved:

  • do not automatically bisect on mozilla-inbound when we finished mozilla-central or a release branch bisection. Merges can comes from fx-team, or another integration branch and this is not really application dependent.
  • try to avoid going back 4 days before the merge when going to the integration branch, there is a loss in productivity since we are likely to test commits that we already tested.

So, how can this be achieved ? Here is my current approach (technical):

  1. Once we are done with the nightlies (one build per day) from a bisection from m-c or any release branch, switch to use taskcluster to download possible builds between. This way we reduce the range to two pushes (one good, one bad) instead of a full day. But since we tested them both, only the commits in the most recent push may contain the regression.
  2. Read the commit message of the top most commit in the most recent push. If it does not looks like a merge commit, then we can’t do anything (maybe this is not a merge, then we are done).
  3. We have a merge push. So now we try to find the exact commits around, on the branch where the merged commits come from.
  4. Bisect this new push range using the changesets and the branch found above, reduce that range and go to 2.

Let’s take an example:

mozregression -g 2015-09-20 -b 2015-10-10

We are bisecting firefox, on mozilla-central. Let’s say we end up with a range 2015-10-01 – 2015-10-02. This is how the pushlog will looks like at the end, 4 pushes and more than 250 changesets.

Now mozregression will automatically reduce the range (still on mozilla-central) by asking you good/bad for those remaining pushes. So, we would end up with two pushes – one we know is good because we tested the top most commit, and the other we know is bad for the same reason. Look at the following pushlog, showing what is still untested (except for the merge commit itself) – 96 commits, coming from m-i.

And then mozregression will detect that it is a merge push from m-i, so automatically it will let you bisect this range of pushes from m-i. That is, our 96 changesets from m-c now converted to testable pushes in m-i. And we will end with a smaller range, for example this one where it will be easy to find our regression because this is one push without any merge.


Comparison

Note that both methods for the example above would have worked. Mainly because we are ending in commits originated from m-i. I tried with another bisection, this time trying to find a commit in fx-team – in that case, current mozregression is simply out – but with the new method it was handled well.

Also using the current method, it would have required around 7 steps after reducing to the one day range for the example above. The new approach can achieve the same with around 5 steps.

Last but not least, this new flow is much more cleaner:

  1. start to bisect from a given branch. Reduce the range to one push on that branch.
  2. if we found a merge, find the branch, the new pushes, and go to 1 to bisect some more with this new data. Else we are done.

Is this applicable ?

Well, it relies on two things. The first one (and we already rely on that a bit currently) is that a merged commit can be found in the branch where it comes from, using the changeset. I have to ask vcs gurus to know if that is reliable, but from my tests this is working well.

Second thing it that we need to detect a merge commit – and from which branch commits comes from. Thanks to the consistency of the sheriffs in their commit messages, this is easy.

Even if it is not applicable everywhere for some reason, it appears that it often works. Using this technique would result in a more accurate and helpful bisection, with speed gain and increased chances to find the root cause of a regression.

This need some more thinking and testing, to determine the limits (what if this doesn’t work ? Should we/can we use the old method in that case ?) but this is definitely something I will explore more to improve the usefulness of mozregression.

mozregression 1.1.0 release

New release of mozregression, with some goodies!

  • Allow to bisect debug builds for inbound
  • Allow to launch a specific release (e.g., –launch 41)
  • [Work in Progress] basic support for b2g devices (firefox os)

See http://mozilla.github.io/mozregression/news.html#1.1.0-release for more details and the full changelog.

Python [aggressive] pep8 conversion using autopep8

Some time ago, I started to look at Talos, the python performance testing framework for firefox that is usable on Windows, Mac and Linux.

Talos has been around for a long time, and has seen many contributors! Unfortunately the codebase reflects that, and as an example there was simply no common code style around for all the Python files.

Sometimes a 2 spaces based indentation, sometimes 4 spaces based, sometimes something else. No limit for the lines length. This end up with something that is really hard to read, understand and maintain. So one of my first goal was to try to clean this up.

And I heard about autopep8. As the name suggests, this is a tool (command line) that will automatically do some pep8 conversion on Python source files.

Awesome! I highly recommend that to you if you are trying to adapt the coding style of some Python code to pep8 convention, this worked really well for me. This is a pain to do that by hand, and almost impracticable when the indentation needs to be fixed, but autopep8 makes that for you in a safe way.

Tip: the –aggressive flag is really nice for fixing long lines.

So, as an example this is how I used autopep8 on talos:

autopep8 --recursive --in-place --aggressive --aggressive /path/to/talos

Simple and effective. See the usage documentation to see with an example what it really does and other command line flags.

RunSnakeRun – graphical visualisation of dumped python profiling data

If you are a Python developer like me, you probably know the profile and cProfile modules that provides deterministic profiling of Python programs.

These modules are awesome – however, when it comes to analysing the data to improve your program, the provided pstats module is generally not powerful enough if you have quite a large codebase.

And here graphical tools comes in handy! I tried RunSnakeRun, and this is a really great program that allows you to analyse the profiling data under multiple angles (a nice view is by file), so you can find easily the bottlenecks and fix them.

RunSnakeRun helped me to improve the “mach help” command. It is a cross platform tool. Note that if you are on GNU/Linux and that you have the KDE desktop (or don’t mind to install the required KDE dependencies), KCacheGrind can be used with Python also.

rcontrol – a new python 2 and 3 ssh high level library

I just started to build a new python library to ease access and control of remote hosts via ssh: rcontrol. It is based on paramiko and offer a high level API to execute remote and local commands in parallel.

rcontrol is an alternative to fabric – but rcontrol is not built with the specific deployment use case in mind, do not use global variables (I really don’t like the fabric global env), is intended to be more user-friendly for tasks synchronisation (doing things in parallel) and finally is compatible with python 3.

This is actually not a Mozilla contribution. Still some part of the library share a piece of code with MozBase, because I reused the same code I wrote in one of the patches, to separate lines of output streams from a process (see bug 794984).

If rcontrol sounds like what you need, give it a try. 🙂 Look at the README for a detailed description and more information about this tool – then at the documentation. If you find a bug or want a new cool feature please report it, or even better create a github pull request (contributions are more than welcome!). And if you like it, star it on github!

Python code cleanup – vulture

I’m pretty sure you all already know about flake8, a great tool that combine other tools (PyFlakes, pep8 and Ned Batchelder’s McCabe script) to check style issues and code errors.

Working on Talos, I needed to find a way to find dead code on the codebase (the less code, the better!). I found a pretty good tool that helped me: vulture. This is a one shot tool – it can not be automated like flake8 as there is some false positives, but still running it once on an old codebase may be a big win to find and remove useless stuff.

Obviously it is easier to use on python programs – you will have to whitelist a lot of things if you run this on a python library that offers a public API.

If you want to seek and destoy dead code on your python program, give it a try!

mozregression-gui first release!

A year from now, I started to contribute to Mozilla. Mozregression (a regression range finder for Mozilla nightly and inbound builds) was one of the first projects that catched my attention: I made one patch, then another, and one again… I was mentored by the awesome William Lachance. Since then, I became one of the core contributors and a packager for mozregression and am now myself mentoring people for new contributions on this project!

At the time of the Google Summer of Code, William and I thought about adding a graphical interface for mozregression. Unfortunately, Mozilla was not accepted for gsoc 2015 – but still the idea was interesting – and we worked on it anyway.

And here we are! Ready for a first release of mozregression-gui! Please give it a try, and help us by reporting bugs and giving feedback. 🙂 For now we provide binaries for Windows and Linux 64 (a Mac port is planned) but it is still possible to build from sources for each platform.

Much work remains to be done on the GUI, and this is a good place to start contributing to Mozilla – so if you’d like to hack with Python and Qt don’t wait and get involved!mozregui