Open Bug 987477 Opened 10 years ago Updated 2 years ago

Add fast path for transform functions

Categories

(Core :: DOM: CSS Object Model, defect, P5)

defect

Tracking

()

People

(Reporter: kgrandon, Unassigned)

References

Details

(Keywords: perf)

Concatenating strings for transform operations can currently be a performance bottleneck. It would be nice if we could have a fast path for transform functions.
Blocks: 987472
(from #layout)
>[2014-03-24 18:19:53 -0700] <roc> dbaron: dunno if you were around but we figured out some ways to optimize this with the help of the JS engine
>[2014-03-24 18:20:11 -0700] <dbaron> roc, optimize what?
>[2014-03-24 18:20:47 -0700] <roc> WebIDL string attribute setters that accept CSS microsyntax
>[2014-03-24 18:21:20 -0700] <roc> the basic idea is that you'd introduce extra setter methods that are used when the string matches particular patterns
>[2014-03-24 18:25:00 -0700] <roc> e.g. you'd declare in WebIDL something like [StringSetter("SetLeftPx", float, "px")] attribute DOMString left;
>[2014-03-24 18:25:41 -0700] <roc> and then any string that is a float followed by "px" can be (but need not be) optimized down to a direct call to SetLeftPx
>[2014-03-24 18:26:08 -0700] <roc> then the JS engine can pattern-match on a RHS expression of the form number + "px"
>[2014-03-24 18:26:41 -0700] <roc> and bypass the stringify - concatenate - parse steps
...
>[2014-03-24 18:39:03 -0700] <roc> anyway if you see any places where this would be useful, we should push on the idea
>[2014-03-24 18:40:36 -0700] <roc> it would also be useful for various canvas things. E.g. [StringSetter("SetFillRGBA", "rgba(", float, ",", float, ",", float, ",", float, ")")] attribute DOMString fillStyle;
>[2014-03-24 18:43:18 -0700] <dbaron> though I suppose there's some question as to whether we couldn't make the parsing code do the same on the CSS side
>[2014-03-24 18:43:51 -0700] <dbaron> oh, I guess if the JS engine is actually going to detect code that does string + "px"
>[2014-03-24 18:44:24 -0700] <roc> yeah, to avoid the stringify - concatenate steps you need JS engine help
>[2014-03-24 18:48:27 -0700] <roc> mchang: can you file (or have you filed) a bug about your performance issues with setting the transform property?
>[2014-03-24 18:50:05 -0700] <mchang> roc: I was going to file a bug, great to hear there’s been some ideas tossed around!
>[2014-03-24 18:50:40 -0700] <mchang> roc: is there a reason to use web idl to do that versus setting a property directly on the style object? e.g. element.style.transform.translateXpx(50) ?
>[2014-03-24 18:51:29 -0700] <roc> yes. The WebIDL approach is just an optimization, it doesn't require new specifications, it works with existing code, and code that uses it will work across browsers
>[2014-03-24 18:51:53 -0700] <roc> please file a bug about your issue
>[2014-03-24 18:52:00 -0700] <roc> then I can file a bug about the general idea
Component: Layout → DOM: CSS Object Model
Sounds like this may be a dupe of bug 987479 if there are no further optimizations we can make for style.transform.
I feel like this is rather relevant to what we are looking for: http://www.xanthir.com/b4UD0

Tab - any chance you would have a moment to label out specifically how something like the following could be optimized using your CSS value proposal?

element.style.transform = 'translate(' + x + 'px,' + y + 'px) scale(' + scale + ')';
Oops, meant to add Tab to this bug. Tab, any thoughts on comment 3 above?
Flags: needinfo?(jackalmage)
My proposal isn't usable yet - it requires Value Objects, which doesn't yet have a real proposal in TC39 (though the idea is well-developed, and they plan to work on it in the next year).

But you'd write it like:

element.css.transform = [CSS.translate(CSS.px(x), CSS.px(y)), CSS.scale(scale)];

(One of the big wins of value objects is the suffix syntax, so you can just write `5px` in your code and have it be identical to `CSS.px(5)`.  Can't do that here, since the number is stored in a variable, so you have to manually convert.)
Flags: needinfo?(jackalmage)
Thanks for the info Tab! Sounds like very exciting stuff and I look forward to what the future holds. 

I'm assuming that value objects are mainly needed so that typeof element.css.transform === "string"?

I'm curious if there would be some way for us to move faster on the rest of the implementation, and have some alternative to setting this until value objects exist. Just an idea - I know there is still a lot of work to be done here, and this probably isn't something to rush on.
> I'm assuming that value objects are mainly needed so that typeof element.css.transform === "string"?

No, actually, nothing's stringly-typed in my proposal except string.  Value Objects bring several useful features to the proposal:

* They allow you to define a numeric prefix, which is a shortened version of calling a specified constructor. This happens to look exactly like a <dimension> value in CSS.

* They are compared via recursive structural equality, rather than reference equality, even when compared with ===.  That means that all instances of `5px` will test as equivalent, regardless of how/where they were constructed.

* They are immutable, which means the engine can optimize and avoid constructing multiple instances of `5px`, because there's no way to tell whether two instances are the same object or different.

* They allow operator overloading, so you can write code like `var len = 5px + 10em;`, rather than `var len = CSS.px(5 + CSS.em(10).px);` or similar.

They are still actual objects, so typeof returns a reasonable result.

> I'm curious if there would be some way for us to move faster on the rest of the implementation, and have some alternative to setting this until value objects exist. Just an idea - I know there is still a lot of work to be done here, and this probably isn't something to rush on.

Unfortunately, you really can't. :/  Value Objects have important properties that can't be usefully faked by existing objects, and I don't think we can get worthwhile optimizations out of an OM API based on normal objects.

That said, depending on what you're looking for, I think fast paths for certain properties, like transform, are possible anyway.  We've discussed in Blink adding an additional transform layer as a DOM property, which takes a DOMMatrix or a TypedArray directly.  This way you get to avoid all the overhead of string parsing, and also of the CSS cascade - this transform just applies after CSS/SVG transforms, and can pretty much just be piped directly to the compositing machinery.  Does this sound interesting, or are you mainly trying to fast-path existing code?
(In reply to Tab Atkins Jr. from comment #7)
> We've discussed in Blink adding an additional transform layer as a DOM property, which takes a
> DOMMatrix or a TypedArray directly.  This way you get to avoid all the
> overhead of string parsing, and also of the CSS cascade - this transform
> just applies after CSS/SVG transforms, and can pretty much just be piped
> directly to the compositing machinery.  Does this sound interesting, or are
> you mainly trying to fast-path existing code?

I think this is definitely preferred to what we have now, and seems like we'd be able to implement this in the meantime while working on CSSOM proposal for the long term. I'm new to the standards world so I will check with some people about how to properly draw up and start thinking about a proposal here.

Thank you so much for the information and ideas - it's much appreciated.
https://bugzilla.mozilla.org/show_bug.cgi?id=1472046

Move all DOM bugs that haven’t been updated in more than 3 years and has no one currently assigned to P5.

If you have questions, please contact :mdaly.
Priority: -- → P5
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.