Posted by: felipe | April 30, 2012

Using about:cc to fix leaks

Last week in Toronto, the Firefox team had a work week. One of the activities was a session with lightning talks about various aspects of Firefox development. I gave a lightning talk on how to use Olli’s about:cc add-on to find a leak in the front-end code, understand it and fix it. I tried to emphasize the importance of not creating leaks not only for memory use but also for the browser’s responsiveness, and preparing for it was a good exercise as it helped me learn more how to use it myself.

Here is the video for it, and the awesomely-formatted slides and links are here.

As an alternative, Honza created a similar add-on that uses the same underlying API and has a more user-friendly UI. It’s called about:ccdump and you can find how to use it in his blog post.

Shameless plug:
if you liked the subject and are interested in helping: both about:cc and about:ccdemo uses the cycle collection API to get the cycles data and analyze it. It would be great if this API was also used as part of our testing framework to analyze the data after a test run and help prevent new bugs being introduced. If you would like to work on it, this is filed as bug 728294.

Posted by: felipe | February 28, 2012

List of existing memory/performance debugging tools

About:jank, about:ccdump, MemChaser, the profiler… I like to follow the development of all these new tools that we are creating help debug and understand our code behavior better, but it’s getting harder to keep track of all of them, and to remember what is the purpose and location of each. What’s the URL for that tool again?, Is about:jank hosted on AMO?

To make this easier I’ve created a list on MDN with all these add-ons (well, all the ones that I could remember). The purpose of this list is to have a short summary of each tool, a description of what it’s useful for, and a simple explanation on how to use it; plus a link to install and to get more information. There were some other similar lists spread accross MDN and the Wiki, but they were mostly outdated, so the reason I started a new page from stratch is to only have tools that are known to be supported and currently working.

Please add anything that I missed and feel free to improve the description or summaries for anything!

Posted by: felipe | February 13, 2012

Telemetry Stopwatch

Last week, I added a small module to make it easier to track time deltas measurements that are meant for telemetry. The module is called TelemetryStopwatch and it has two functions, start and finish, which do what their name imply. When you call start it takes a timestamp, and when you call finish it calculates the delta and adds the data to the chosen histogram. It’s useful to avoid sticking start timestamps as enclosed variables or private members in objects, and in cases where the start and stop measurements are disjoint and there’s not a good place to store the stamp or add code to calculate the diff.

Cu.import("resource:///modules/TelemetryStopwatch.jsm");
TelemetryStopwatch.start("MY_TELEMETRY_HISTOGRAM");
// and later
TelemetryStopwatch.finish("MY_TELEMETRY_HISTOGRAM");

// or, with the optional object parameter:
TelemetryStopwatch.start("MY_TELEMETRY_HISTOGRAM", refObj);
TelemetryStopwatch.finish("MY_TELEMETRY_HISTOGRAM", refObj);

You can have multiple counters at the same time. Each counter is associated with a telemetry histogram, or with a histogram + a reference object, for cases where you might need more than 1 timer running at the same time for the same histogram (e.g. some measurements related to a specific tab, where more than 1 tab might have it running at the same time). The objects are tracked on a WeakMap so you don’t have to worry about leaks. The module is in toolkit to make it widely available.
Happy metering!

Posted by: felipe | February 2, 2012

A proposal to drop browser vendor prefixes

Which reaction do you get by looking at the following code?

#elem {
  -moz-box-shadow: 0 0 10px gray;
  -webkit-box-shadow: 0 0 10px gray;
  -o-box-shadow: 0 0 10px gray;
  -ms-box-shadow: 0 0 10px gray;
  box-shadow: 0 0 10px gray;
}

Whenever you see some extremely verbose CSS like the above, written with all vendor prefixes (plus the unprefixed version), all of which look exactly the same, it really brings some rage mixed feelings. On one hand, you feel glad to have found a web developer who went out of their way to use experimental CSS features in the “right” way. On the other hand, you feel sad that we are asking them to do this.

Much has been said  about how CSS prefixes do more harm than good, and a lot of people have wanted to get rid of them, but there hasn’t been any proposal that didn’t cause (worse) shortcomings, allowed vendor experimentation to continue without disrupting the web, or offered an easy transition path. I’ll present here a proposal that I believe fixes all the existing problems with prefixes, makes it really easy to transition from experimental to recommended, and actually improves various aspects of web development and browser support for features that are on an standardization path.

The feature is simple, and there’s a TL;DR at the end, but let’s design it step by step to make sure we’ve covered everything.

(Let me here preemptively say, in true Graydon style: disregard the syntax of the proposal, focus only on the idea. The ideal syntax can be discussed later)

Feature unlocking

The basic idea is that, in order to use non-standard CSS features, instead of using prefixes on every declaration of that property, you only use it once at the top of the file to indicate that you’re willing to unlock that feature as implemented by that engine. For instance, the example at the top would become:

@-vendor-unlock {
  box-shadow: gecko, webkit, trident, opera;
}
...
#elem {
  box-shadow: 0 0 10px gray;
}

That means that the actual property declarations do not need to use the prefix, but the browser engine will still only accept the declaration if it has been explicitly unlocked. With that, when the feature reaches the status in which a vendor would like to drop the prefix (that is, by convention, candidate recommendation), all it needs is to start accepting the declaration unconditionally (that is, independent of being unlocked), without breaking every website that was using it before (unless the syntax changes, but more on that later).

Here’s a list of the properties that this approach bring:

  • Feature experimentation is still not unintentionally exposed to the web
  • It’s easier for web developers to use, which should encourage usage and testing for more than one engine
  • It makes it explicit for web developers that they are dealing with an experimental feature (instead of the “engine-only” feeling of prefixes)
  • When it’s time to make the feature a standard, websites don’t have to break and the engines don’t have to support the legacy syntax for a painfully long period of time
  • It allows the creation of developer tools for web developers (and browser developers) to force support a feature and thus test their website with a different engine
  • Browser vendors can start shipping new features with this approach without breaking existing support, and it doesn’t require a multi-year transition
  • Users will benefit from quicker multi-browser support by websites
  • It makes it easier for new engines to enter the market

Versioning

One problem that already exists with vendor prefixes, but that is not solved with the above suggestion, is syntax or feature changes. The whole purpose of the prefixes is so that vendors can experiment with feature support without making the promise that it won’t ever change. In practice, though, once a feature has been widespread enough, most vendors are tied to that and the decision to change the syntax or not is heavily influenced by that. While we are designing the new approach, we can also fix that! With feature versioning, web developers can explicitly target a version of the implementation, like so:

@-vendor-unlock {
  box-shadow: gecko/v1, webkit/v2, trident/v2, opera/v1;
}

This gives us:

  • Different implementations of a feature can exist at the same time
  • When the engines are tending towards an unified version (say 1st version of a feature in gecko was different than 1st in webkit, but they match at version 2), it’s easier for developers to use it
  • When there’s a change in the syntax or behavior of a feature, the browser engine can choose to either gracefully support the previous version or not, on a case by case decision whenever it makes sense to do so. This is currently not possible since there’s no way to tell which version the webpage is expecting to use.

Syntax mismatches

The last problem is when two matching versions does not exist between browsers. That is, it’s not possible to write a single declaration that will work on different engines. In that case, there’s no way around having multiple property declarations, and an override must be provided. To do that, the vendor prefix plus the version is used, and the feature still has to be unlocked, which guarantees that there’s no reason to just use the “good old prefix” except for mismatching reasons. Also, the prefix should be used to the engine that is probably leaning in the wrong direction than what will be made the standard.

As an example, let’s imagine a property called foobar that webkit and gecko implements, with two size arguments (<left> and <right>), but each takes on a different order.

@-vendor-unlock {
  foobar: gecko/v1, webkit/v1;
}
#elem {
  foobar: 10px 5px;
  -webkit-foobar-v1: 5px 10px;
}

Now, let’s say that webkit decided to change the order to match gecko’s, and the other engines followed. Then the only change required is to add the other engines and another entry for the second version of webkit:
@-vendor-unlock {
  foobar: gecko/v1, webkit/v1, webkit/v2, opera/v1, trident/v1;
}
#elem {
  foobar: 10px 5px;
  -webkit-foobar-v1: 5px 10px;
}

With this change, the webpage supports the experimental versions of foobar, plus the standardized (unprefixed) version whenever it reaches candidate recommendation, plus the differing version 1 in webkit if it wants to.

TL;DR

Browser vendor prefixes are polluting the web so much while making web development harder, which is the exact opposite of the two main reasons it exists. The main idea to fix that is that the property declarations should be written unprefixed, while an explicit unlock and versioning is instead used to activate these features on browser engines. An example would be:

@-vendor-unlock {
  border-radius: gecko/v2, webkit/v1, opera/v1, trident/v1;
}
...
#elem {
  border-top-left-radius: 5px;
  border-top-right-radius: 10px;
}

Note that with this example I also implied that the unlocking mechanism can be used for whole features, not only direct property names, such that you could use “css-animations” to unlock all the animation-delay, animation-timing-function, @keyframes, etc.

P.S.: I’ll be at FOSDEM this weekend if anyone is interested in discussing this idea during the conference.

Older Posts »

Categories

Follow

Get every new post delivered to your Inbox.