Intent to Implement: Geometry Interfaces

802 views
Skip to first unread message

Jinho Bang

unread,
Jun 25, 2014, 12:51:27 PM6/25/14
to blin...@chromium.org

Contact emails

jinho...@samsung.com, caba...@adobe.com, dsch...@chromium.org


Spec

http://dev.w3.org/fxtf/geometry/


Summary

The specification provides basic geometric interfaces to represent points, rectangles,

quadrilaterals and transformation matrices that can be used by other modules or specifications.


We will implement following things:

- DOMMatrix Interface

- DOMRect Interface

- DOMRectList Interface

- DOMQuad Interface

- DOMPoint interface


Motivation

The SVG interfaces SVGPoint, SVGRect and SVGMatrix are aliasing the here defined interfaces

in favor for common interfaces used by SVG, Canvas 2D Context  and CSS Transforms.


Compatibility Risk

Low, These are already being implemented in Firefox and WebKit (Rik and Dirk)


Ongoing technical constraints

None


Will this feature be supported on all five Blink platforms (Windows, Mac, Linux, Chrome OS and Android)?

Yes


OWP launch tracking bug?

http://crbug.com/388780


Link to entry on the feature dashboard

http://www.chromestatus.com/features/6015941766807552


Requesting approval to ship?

No


Domenic Denicola

unread,
Jun 25, 2014, 1:03:07 PM6/25/14
to blin...@chromium.org
On Wednesday, June 25, 2014 12:51:27 PM UTC-4, Jinho Bang wrote:

- DOMRectList Interface



We should not implement this. New fake-arrays are an antipattern. Raised in standards space by Anne at https://www.w3.org/Bugs/Public/show_bug.cgi?id=26200

I have also filed https://www.w3.org/Bugs/Public/show_bug.cgi?id=26201 to add constructors to the *ReadOnly interfaces.

Rik Cabanier

unread,
Jun 25, 2014, 1:06:00 PM6/25/14
to Jinho Bang, blink-dev
On Wed, Jun 25, 2014 at 9:51 AM, Jinho Bang <jinho...@samsung.com> wrote:

Contact emails

jinho...@samsung.com, caba...@adobe.com, dsch...@chromium.org


Spec

http://dev.w3.org/fxtf/geometry/


Summary

The specification provides basic geometric interfaces to represent points, rectangles,

quadrilaterals and transformation matrices that can be used by other modules or specifications.


We will implement following things:

- DOMMatrix Interface

- DOMRect Interface

- DOMRectList Interface

- DOMQuad Interface

- DOMPoint interface


Motivation

The SVG interfaces SVGPoint, SVGRect and SVGMatrix are aliasing the here defined interfaces

in favor for common interfaces used by SVG, Canvas 2D Context  and CSS Transforms.


Compatibility Risk

Low, These are already being implemented in Firefox and WebKit (Rik and Dirk)


FYI all these interfaces landed in Firefox and are available in the nightly builds.
 

Ongoing technical constraints

None


Will this feature be supported on all five Blink platforms (Windows, Mac, Linux, Chrome OS and Android)?

Yes


OWP launch tracking bug?

http://crbug.com/388780


Link to entry on the feature dashboard

http://www.chromestatus.com/features/6015941766807552


Requesting approval to ship?

No


To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Dirk Schulze

unread,
Jun 25, 2014, 1:31:57 PM6/25/14
to Domenic Denicola, blin...@chromium.org

On Jun 25, 2014, at 7:03 PM, Domenic Denicola <dom...@domenicdenicola.com> wrote:

> On Wednesday, June 25, 2014 12:51:27 PM UTC-4, Jinho Bang wrote:
>
> - DOMRectList Interface
>

Thanks for filing the bug reports. I commented to all of them.

>
> We should not implement this. New fake-arrays are an antipattern. Raised in standards space by Anne at https://www.w3.org/Bugs/Public/show_bug.cgi?id=26200

DOMRectList has been an ArrayClass before. This was discussed and the WebIDL editor strongly suggested not to use ArrayClass. But the getter and the length attribute make it behave similar to arrays.

>
> I have also filed https://www.w3.org/Bugs/Public/show_bug.cgi?id=26201 to add constructors to the *ReadOnly interfaces.

I commented on this bug report as well. There is no need for authors to construct a DOMRectReadOnly or any of the other interfaces. These interfaces are designed for the use by the UA directly. The UA can provide metrics that update live but are not modifiable by the author. Strong candidates to use these interfaces are CSSOM View[1] and SVG.

Greetings,
Dirk

[1] http://dev.w3.org/csswg/cssom-view/#the-geometryutils-interface

Boris Zbarsky

unread,
Jun 25, 2014, 2:57:10 PM6/25/14
to blink-dev
On 6/25/14, 1:29 PM, Dirk Schulze wrote:
> DOMRectList has been an ArrayClass before. This was discussed and the WebIDL editor strongly suggested not to use ArrayClass. But the getter and the length attribute make it behave similar to arrays.

I think the point Domenic is making is that the places that currently
return DOMRectList should just return a sequence<DOMRect>.

This is only viable if existing consumers don't use item() on these
lists, of course... Apart from that, I think returning a sequence here
is totally the way to go.

-Boris

Domenic Denicola

unread,
Jun 25, 2014, 3:11:12 PM6/25/14
to Boris Zbarsky, blink-dev
From: blin...@chromium.org <blin...@chromium.org> on behalf of Boris Zbarsky <bzba...@MIT.EDU>

> I think the point Domenic is making is that the places that currently return DOMRectList should just return a sequence<DOMRect>.

Yes, exactly.

When I originally wrote the email, I wasn't aware that there are parts of the platform already making use of DOMRectList, since my impression this was an intent to implement new interfaces. It looks like at the least getClientRects does; does anyone else?

I see two paths forward:

- If implementers are willing to try it, converting to a real array (WebIDL "sequence") would be ideal and greatly improve the developer experience.
- If we don't want to spend the time testing such a change (which is understandable), then I'd recommend DOMRectList get [NoInterfaceObject], and rename it LegacyGetClientRectsReturnValueType or some such so that it gets hidden as far away from developers as possible, and so no spec uses it in the future.

Rik Cabanier

unread,
Jun 25, 2014, 3:33:17 PM6/25/14
to Boris Zbarsky, blink-dev

Boris Zbarsky

unread,
Jun 25, 2014, 3:39:57 PM6/25/14
to Domenic Denicola, blink-dev
On 6/25/14, 3:11 PM, Domenic Denicola wrote:
> It looks like at the least getClientRects does; does anyone else?

Not that I can see. (Gecko has another use, but it's in an internal
paint-region event that's not standardized.)

Note that a possible viable option is to return an actual Array
subclass; then we can keep our item() method and all that.

-Boris

Anne van Kesteren

unread,
Jun 25, 2014, 3:55:23 PM6/25/14
to Boris Zbarsky, Domenic Denicola, blink-dev
On Wed, Jun 25, 2014 at 9:39 PM, Boris Zbarsky <bzba...@mit.edu> wrote:
> Note that a possible viable option is to return an actual Array subclass;
> then we can keep our item() method and all that.

I think we should consider that if there's more places we could use
such an Array.


--
http://annevankesteren.nl/

Rik Cabanier

unread,
Jun 25, 2014, 4:05:23 PM6/25/14
to Anne van Kesteren, Boris Zbarsky, Domenic Denicola, blink-dev
Are you saying that we should replace the current API with a subclassed array class but only if this subclass will be used in other places? 

Also, does anyone know of other web platform classes that subclasses a javascript array?

Anne van Kesteren

unread,
Jun 25, 2014, 4:08:22 PM6/25/14
to Rik Cabanier, Boris Zbarsky, Domenic Denicola, blink-dev
On Wed, Jun 25, 2014 at 10:05 PM, Rik Cabanier <caba...@gmail.com> wrote:
> Are you saying that we should replace the current API with a subclassed
> array class but only if this subclass will be used in other places?

I'm not sure introducing a subclass of Array with item() is worth it
for this specific legacy *List interface. But if we can replace a
bunch of them...


> Also, does anyone know of other web platform classes that subclasses a
> javascript array?

It's ES6 territory, so not implemented. But there's query()/queryAll()
that want it.


--
http://annevankesteren.nl/

Erik Arvidsson

unread,
Jun 25, 2014, 4:17:16 PM6/25/14
to Rik Cabanier, Anne van Kesteren, Boris Zbarsky, Domenic Denicola, blink-dev
DOMExceptions have Error.prototype in their prototype chain but the instance is an exotic object and not an ordinary object.



--
erik


Rik Cabanier

unread,
Jun 25, 2014, 5:32:19 PM6/25/14
to Anne van Kesteren, Boris Zbarsky, Domenic Denicola, blink-dev
On Wed, Jun 25, 2014 at 1:08 PM, Anne van Kesteren <ann...@annevk.nl> wrote:
On Wed, Jun 25, 2014 at 10:05 PM, Rik Cabanier <caba...@gmail.com> wrote:
> Are you saying that we should replace the current API with a subclassed
> array class but only if this subclass will be used in other places?

I'm not sure introducing a subclass of Array with item() is worth it
for this specific legacy *List interface. But if we can replace a
bunch of them...

Given this, maybe we should just stick with the current definition.
If we decide later that it needs the additional array-like behavior, we can add it then.

I do agree with Dominic that we should make it a [NoInterfaceObject] object.

Domenic Denicola

unread,
Jun 25, 2014, 5:36:45 PM6/25/14
to Rik Cabanier, Anne van Kesteren, Boris Zbarsky, blink-dev
From: Rik Cabanier <caba...@gmail.com>

> Given this, maybe we should just stick with the current definition.
> If we decide later that it needs the additional array-like behavior, we can add it then.

The question is, do we ever expect developers to use this type? If so, we should fix it as soon as is feasible (i.e., as soon as browser ship ES6 built-in subclassing). If no new code uses getClientRects(), e.g. because getBoxQuads() is better, then I guess we can just leave it as another warty old API.

> I do agree with Dominic that we should make it a [NoInterfaceObject] object.

We should also ensure no other specs ever use this type, with an appropriately-scary name, and probably a note in the spec as well.

Rik Cabanier

unread,
Jun 25, 2014, 5:56:15 PM6/25/14
to Domenic Denicola, Anne van Kesteren, Boris Zbarsky, blink-dev
On Wed, Jun 25, 2014 at 2:36 PM, Domenic Denicola <dom...@domenicdenicola.com> wrote:
From: Rik Cabanier <caba...@gmail.com>

> Given this, maybe we should just stick with the current definition.
> If we decide later that it needs the additional array-like behavior, we can add it then.

The question is, do we ever expect developers to use this type? If so, we should fix it as soon as is feasible (i.e., as soon as browser ship ES6 built-in subclassing). If no new code uses getClientRects(), e.g. because getBoxQuads() is better, then I guess we can just leave it as another warty old API.

This is a legacy API. As you note, getBoxQuads() is the way forward and it returns a proper array.
 
> I do agree with Dominic that we should make it a [NoInterfaceObject] object.

We should also ensure no other specs ever use this type, with an appropriately-scary name, and probably a note in the spec as well.

I agree that we need a note, but changing the name seems like overkill,

Tab Atkins Jr.

unread,
Jun 25, 2014, 7:43:40 PM6/25/14
to Rik Cabanier, Domenic Denicola, Anne van Kesteren, Boris Zbarsky, blink-dev
Eh, names that clearly indicate legacy-ness are great; without it,
even with a note it's too easy for other spec authors to accidentally
use it. If they're forced to type a stupid-looking name when writing
their spec, they'll at least question their decision, and it'll jump
out at any reviewers.

~TJ

Rik Cabanier

unread,
Jun 25, 2014, 11:01:29 PM6/25/14
to Tab Atkins Jr., Domenic Denicola, Anne van Kesteren, Boris Zbarsky, blink-dev
Are there examples where objects or methods were given names to indicate that they are legacy?
I worry about possible pushback if this would be the first one. 

Boris Zbarsky

unread,
Jun 25, 2014, 11:14:23 PM6/25/14
to Rik Cabanier, Tab Atkins Jr., Domenic Denicola, Anne van Kesteren, blink-dev
On 6/25/14, 11:01 PM, Rik Cabanier wrote:
> Are there examples where objects or methods were given names to indicate
> that they are legacy?

Web IDL has "legacycaller".

Typically you don't get to change the name of something that is legacy
because people are depending on the existing name. We're just assuming
that in this case no one in fact depends on the name. If that's the
case, clearly labeling it as legacy makes sense to me.

-Boris

Domenic Denicola

unread,
Jun 25, 2014, 11:53:45 PM6/25/14
to Boris Zbarsky, Rik Cabanier, Tab Atkins Jr., Anne van Kesteren, blink-dev
From: blin...@chromium.org [mailto:blin...@chromium.org] On Behalf Of Boris Zbarsky

> We're just assuming that in this case no one in fact depends on the name.

And notably, the CSSWG also assumes this, since they're changing it from ClientRectList to DOMRectList.

Rik Cabanier

unread,
Jun 26, 2014, 12:02:18 AM6/26/14
to Domenic Denicola, Boris Zbarsky, Tab Atkins Jr., Anne van Kesteren, blink-dev
WebKit/Blink currently use 'ClientRectList' while Mozilla always had 'DOMRectList'.
Given the feedback, we should rename DOMRectList to LegacyDOMRectList and put a note in the spec.

Dirk has some reservations about adding [NoInterfaceObject]. Is the intent of adding it just to discourage people from extending it?
We might run into compat issues since this object is available and not guarded by this flag.

Anne van Kesteren

unread,
Jun 26, 2014, 2:02:28 AM6/26/14
to Rik Cabanier, Domenic Denicola, Boris Zbarsky, Tab Atkins Jr., blink-dev
On Thu, Jun 26, 2014 at 6:02 AM, Rik Cabanier <caba...@gmail.com> wrote:
> Dirk has some reservations about adding [NoInterfaceObject]. Is the intent
> of adding it just to discourage people from extending it?

From relying on it being there. So that e.g. we can introduce a
subclass of Array later or some such.


> We might run into compat issues since this object is available and not
> guarded by this flag.

We just discussed how it has different names across engines. We would
likely have already run into issues.


--
http://annevankesteren.nl/

Rik Cabanier

unread,
Jun 26, 2014, 2:43:55 AM6/26/14
to Anne van Kesteren, Domenic Denicola, Boris Zbarsky, Tab Atkins Jr., blink-dev
Do you need to know the name? It seems you could use 'getProtoTypeOf' [1] to extend an instance.
I don't have data on people extending it that way though.

Dirk Schulze

unread,
Jun 26, 2014, 4:32:31 AM6/26/14
to Anne van Kesteren, Rik Cabanier, Domenic Denicola, Boris Zbarsky, Tab Atkins Jr., blink-dev
I do not really care about the name of the interface. Should everyone agree that DOMRectList must not be used with the exception of getClientRects than we can rename it to LegacyDOMRectList and Simon or I can clearly state the restrictions in the spec.

I am not sure if [NoInterfaceObject] is really relevant. After talking with Cameron again, he now thinks it is fine to use [ArrayClass]. However, since it seems that we don’t want to use DOMRectList anywhere else than for getClientRects, I would prefer going with the minimal subset implemented by all browsers. The currently specified behavior is the subset that is implemented by WebKit, Blink and Gecko (didn’t check IE yet).

Greetings,
Dirk

>
>
> --
> http://annevankesteren.nl/

Ojan Vafai

unread,
Jul 15, 2014, 6:53:55 PM7/15/14
to Dirk Schulze, Anne van Kesteren, Rik Cabanier, Domenic Denicola, Boris Zbarsky, Tab Atkins Jr., blink-dev
The API owners discussed this and this sounds good to implement as there doesn't seem be significant opposition and the spec is in last call.

Personally, I'd really like to see the list vs array thing resolved before we ship though. I think it's really a bummer for us to ship  array-like types that don't have all the array built-ins. I'm not sure what the reason was for recommending not to use ArrayClass. I'd be happy with any solution that exposes array built-ins on the list, including sequence, ArrayClass or Boris's idea of using a subclass of array.

PhistucK

unread,
Jul 18, 2014, 5:29:35 PM7/18/14
to Rik Cabanier, Boris Zbarsky, blink-dev
Note that only the first link is a JavaScript file. The other two are C# and unrelated.


PhistucK


To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Philip Rogers

unread,
Aug 26, 2014, 3:41:21 PM8/26/14
to PhistucK, Rik Cabanier, Boris Zbarsky, blink-dev
I am concerned about the performance of these APIs, particularly DOMMatrix.

A javascript polyfill will be faster than the native DOMMatrix as it's implemented today. I do not think we should be dropping performance landmines for graphics developers to trip over, even at the cost of making the APIs more complex (e.g., taking typed arrays instead of slow objects).

Is performance a concern? Can we do something better on the implementation side?

Rik Cabanier

unread,
Aug 26, 2014, 5:27:22 PM8/26/14
to Philip Rogers, PhistucK, Boris Zbarsky, blink-dev
On Tue, Aug 26, 2014 at 12:40 PM, Philip Rogers <p...@chromium.org> wrote:
I am concerned about the performance of these APIs, particularly DOMMatrix.

A javascript polyfill will be faster than the native DOMMatrix as it's implemented today. I do not think we should be dropping performance landmines for graphics developers to trip over, even at the cost of making the APIs more complex (e.g., taking typed arrays instead of slow objects).

Is performance a concern?

It would be great to have some data on the performance. It's likely that crossing into the c++ side takes up more cycles than the actual implementation :-)
Jinho did want to implement it using blink-in-javascript but had to abandon that idea since it doesn't support constructors.
 
Can we do something better on the implementation side?

For the typical use case of querying the DOM or manipulating values in it, I doubt that this will have an impact since that wouldn't involve that many matrices (compared to something like WebGL)

Maybe we can do a simple benchmark that measures the duration of matrix operations?
With that information, we can guess how much time is spent in DOMMatrix when you animate a large number of elements at 60fps.

Philip Rogers

unread,
Aug 26, 2014, 6:01:31 PM8/26/14
to Rik Cabanier, PhistucK, Boris Zbarsky, blink-dev
Rik,

I've now read the webkit [1] and mozilla [2] threads on this topic and it looks like these issues have been covered before. I do not think we should ship the geometry interfaces in Blink. DOMMatrix and friends will be slow in Blink for the same reasons WebKit balked at them [3]. As the blink-in-js docs [4] say, blink-in-js should not be used for high-performance apis like this. Maybe we can use typed arrays for these APIs instead?

An alternative is to implement and standardize these interfaces as first-class citizens in Ecmascript.

Adam Barth

unread,
Aug 26, 2014, 8:05:38 PM8/26/14
to Rik Cabanier, Philip Rogers, PhistucK, Boris Zbarsky, blink-dev
On Tue Aug 26 2014 at 2:27:20 PM Rik Cabanier <caba...@gmail.com> wrote:
On Tue, Aug 26, 2014 at 12:40 PM, Philip Rogers <p...@chromium.org> wrote:
I am concerned about the performance of these APIs, particularly DOMMatrix.

A javascript polyfill will be faster than the native DOMMatrix as it's implemented today. I do not think we should be dropping performance landmines for graphics developers to trip over, even at the cost of making the APIs more complex (e.g., taking typed arrays instead of slow objects).

Is performance a concern?

It would be great to have some data on the performance. It's likely that crossing into the c++ side takes up more cycles than the actual implementation :-)
Jinho did want to implement it using blink-in-javascript but had to abandon that idea since it doesn't support constructors.

To clarify: Blink-in-JS is not fast.  It's strictly slower than the current implementation.  Blink-in-JS is optimized for maintainability, not performance.

Adam

Rik Cabanier

unread,
Aug 27, 2014, 2:24:23 PM8/27/14
to Philip Rogers, PhistucK, Boris Zbarsky, blink-dev
On Tue, Aug 26, 2014 at 3:01 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

I've now read the webkit [1] and mozilla [2] threads on this topic and it looks like these issues have been covered before. I do not think we should ship the geometry interfaces in Blink. DOMMatrix and friends will be slow in Blink for the same reasons WebKit balked at them [3]. As the blink-in-js docs [4] say, blink-in-js should not be used for high-performance apis like this. Maybe we can use typed arrays for these APIs instead?

Like you said, we covered that approach in the past. Typed arrays are not author friendly and will need additional JS libraries to make them useful.
I also doubt that type arrays will be faster as the C++ side will now have to look into the JS VM to get the values out.

DOMMatrix as currently proposed, is basically a drop-in replacement of the existing SVGMatrix class along with some extra methods and abstractions to address its shortcomings. (I noticed that we didn't add DOMMatrixInit to the spec yet. It's a dictionary with the attributes of DOMMatrix and will be used in methods that take a DOMMatrix as an argument)
 
An alternative is to implement and standardize these interfaces as first-class citizens in Ecmascript.

I believe Dirk looked into this and it didn't look encouraging.

I think we need hard data to see if there's actually a problem. I will try to run some tests and come back with results.

Adam Barth

unread,
Aug 27, 2014, 2:32:14 PM8/27/14
to Rik Cabanier, Philip Rogers, PhistucK, Boris Zbarsky, blink-dev
On Wed Aug 27 2014 at 11:24:18 AM Rik Cabanier <caba...@gmail.com> wrote:
On Tue, Aug 26, 2014 at 3:01 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

I've now read the webkit [1] and mozilla [2] threads on this topic and it looks like these issues have been covered before. I do not think we should ship the geometry interfaces in Blink. DOMMatrix and friends will be slow in Blink for the same reasons WebKit balked at them [3]. As the blink-in-js docs [4] say, blink-in-js should not be used for high-performance apis like this. Maybe we can use typed arrays for these APIs instead?

Like you said, we covered that approach in the past. Typed arrays are not author friendly and will need additional JS libraries to make them useful.
I also doubt that type arrays will be faster as the C++ side will now have to look into the JS VM to get the values out.

DOMMatrix as currently proposed, is basically a drop-in replacement of the existing SVGMatrix class along with some extra methods and abstractions to address its shortcomings. (I noticed that we didn't add DOMMatrixInit to the spec yet. It's a dictionary with the attributes of DOMMatrix and will be used in methods that take a DOMMatrix as an argument)
 
An alternative is to implement and standardize these interfaces as first-class citizens in Ecmascript.

I believe Dirk looked into this and it didn't look encouraging.

What's not encouraging about it?  It would be a shame to not build the technically best solution.

I think we need hard data to see if there's actually a problem. I will try to run some tests and come back with results.

Thanks!
Adam

Rik Cabanier

unread,
Sep 3, 2014, 1:30:19 PM9/3/14
to Philip Rogers, PhistucK, Boris Zbarsky, blink-dev
On Tue, Aug 26, 2014 at 3:01 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

I've now read the webkit [1] and mozilla [2] threads on this topic and it looks like these issues have been covered before. I do not think we should ship the geometry interfaces in Blink. DOMMatrix and friends will be slow in Blink for the same reasons WebKit balked at them [3]. As the blink-in-js docs [4] say, blink-in-js should not be used for high-performance apis like this. Maybe we can use typed arrays for these APIs instead?

I wrote a small test case: http://jsperf.com/dommatrix-perf
It applies a typical translate/scale/rotate sequence to a DOMMatrix and a JS equivalent.

Benchmarking this in Firefox Nightly (because the functionality is not in Chrome yet) shows that the JS implementation is 3 to 4 times faster. This is expected since crossing into the c++ side slows things down.

To make a more realistic case, I added another test that calls setLineDash with the JS array to simulate a DOM crossing. I verified that the C++ side just verifies the contents of that array and stores it in the canvas state. That test is almost twice as slow as the DOMMatrix test.
(I also tried typed arrays but they were slower than native JS arrays)

This tells me that there is no performance problem with DOMMatrix.

In addition, jsperf reports that on my core i-7 3.4 GHz, I can do 360,000 translate/scale/rotate sequences per second.
So, if I animate 100 objects simultaneously, DOMMatrix will only take up: 100 objects * 60fps / 360,0000 ops = 0.017s
 
An alternative is to implement and standardize these interfaces as first-class citizens in Ecmascript.

Yes, that is something that we could do if we discover that people use DOMMatrix so much that it becomes a bottleneck. 
However, since that has no effect on actual author code, it shouldn't stop us from implementing this in c++ today

Adam Barth

unread,
Sep 3, 2014, 4:06:32 PM9/3/14
to Rik Cabanier, Philip Rogers, PhistucK, Boris Zbarsky, blink-dev
On Wed Sep 03 2014 at 10:30:16 AM Rik Cabanier <caba...@gmail.com> wrote:
On Tue, Aug 26, 2014 at 3:01 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

I've now read the webkit [1] and mozilla [2] threads on this topic and it looks like these issues have been covered before. I do not think we should ship the geometry interfaces in Blink. DOMMatrix and friends will be slow in Blink for the same reasons WebKit balked at them [3]. As the blink-in-js docs [4] say, blink-in-js should not be used for high-performance apis like this. Maybe we can use typed arrays for these APIs instead?

I wrote a small test case: http://jsperf.com/dommatrix-perf
It applies a typical translate/scale/rotate sequence to a DOMMatrix and a JS equivalent.

Benchmarking this in Firefox Nightly (because the functionality is not in Chrome yet) shows that the JS implementation is 3 to 4 times faster. This is expected since crossing into the c++ side slows things down.

To make a more realistic case, I added another test that calls setLineDash with the JS array to simulate a DOM crossing. I verified that the C++ side just verifies the contents of that array and stores it in the canvas state. That test is almost twice as slow as the DOMMatrix test.
(I also tried typed arrays but they were slower than native JS arrays)

This tells me that there is no performance problem with DOMMatrix.

3-4x slower seems like a performance problem...

In addition, jsperf reports that on my core i-7 3.4 GHz, I can do 360,000 translate/scale/rotate sequences per second.
So, if I animate 100 objects simultaneously, DOMMatrix will only take up: 100 objects * 60fps / 360,0000 ops = 0.017s

How long does it take on a phone?  Do you think the web platform can afford to give away 3-4x performance and still be competitive on mobile?

Adam

Rik Cabanier

unread,
Sep 3, 2014, 5:35:55 PM9/3/14
to Adam Barth, Philip Rogers, PhistucK, Boris Zbarsky, blink-dev
On Wed, Sep 3, 2014 at 1:06 PM, Adam Barth <aba...@chromium.org> wrote:
On Wed Sep 03 2014 at 10:30:16 AM Rik Cabanier <caba...@gmail.com> wrote:
On Tue, Aug 26, 2014 at 3:01 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

I've now read the webkit [1] and mozilla [2] threads on this topic and it looks like these issues have been covered before. I do not think we should ship the geometry interfaces in Blink. DOMMatrix and friends will be slow in Blink for the same reasons WebKit balked at them [3]. As the blink-in-js docs [4] say, blink-in-js should not be used for high-performance apis like this. Maybe we can use typed arrays for these APIs instead?

I wrote a small test case: http://jsperf.com/dommatrix-perf
It applies a typical translate/scale/rotate sequence to a DOMMatrix and a JS equivalent.

Benchmarking this in Firefox Nightly (because the functionality is not in Chrome yet) shows that the JS implementation is 3 to 4 times faster. This is expected since crossing into the c++ side slows things down.

To make a more realistic case, I added another test that calls setLineDash with the JS array to simulate a DOM crossing. I verified that the C++ side just verifies the contents of that array and stores it in the canvas state. That test is almost twice as slow as the DOMMatrix test.
(I also tried typed arrays but they were slower than native JS arrays)

This tells me that there is no performance problem with DOMMatrix.

3-4x slower seems like a performance problem...

I talked to the mozilla people and this is a bug in the JIT in Firefox for Windows. 
On Mac and Linux, DOMMatrix is actually faster than the JS implementation with no DOM interaction.

I also added tests that use float arrays. They are about the same speed as DOMMatrix as long as you don't interact with the DOM. As soon as you cross the DOM, native JS is 4 to 5 times slower than DOMMatrix.

Test results:
Browser              |  Native  |   JS equivalent  | JS equivalent + DOM access | JS equivalent floatArray |  JS equivalent floatArray + DOM access
Firefox Mac            11.57            10.77                             7.88                                    11.78                                           3.27
FireFox Android       9.11              6.34                             1.89                                    14.08                                           0.52
Chrome Mac            NA                9.27                             3.46                                    10.7                                             3.08
Safari                       NA                9.28                             0.67                                    10.96                                           0.66

Across the board, you can see that interacting with the DOM has a significant impact on performance.
 
In addition, jsperf reports that on my core i-7 3.4 GHz, I can do 360,000 translate/scale/rotate sequences per second.
So, if I animate 100 objects simultaneously, DOMMatrix will only take up: 100 objects * 60fps / 360,0000 ops = 0.017s

How long does it take on a phone?  Do you think the web platform can afford to give away 3-4x performance and still be competitive on mobile?

With the latest numbers, DOMMatrix is much faster than going with a JS or float array implementation. 
It even rivals pure JS implementations if you use raw matrices.

In addition, one of DOMMatrix' main use cases it to interact with the CSS OM for matrix CSS transforms. 
Today people have to run regular expressions and stringifiers to get/set that information which is extremely slow. I can write another benchmark if you want precise numbers.

Boris Zbarsky

unread,
Sep 3, 2014, 7:21:46 PM9/3/14
to blink-dev
On 9/3/14, 5:35 PM, Rik Cabanier wrote:
> I talked to the mozilla people and this is a bug in the JIT in Firefox
> for Windows.
> On Mac and Linux, DOMMatrix is actually faster than the JS
> implementation with no DOM interaction.

I doubt it's a bug in the JIT. It's the _native_ version that's slower
on Windows, not the JS version! In any case, it's definitely a
Windows-specific issue.

> I also added tests that use float arrays. They are about the same speed
> as DOMMatrix as long as you don't interact with the DOM. As soon as you
> cross the DOM, native JS is 4 to 5 times slower than DOMMatrix.

If you pass to a DOM method that expects a sequence<float>, sure: Gecko
doesn't have a fast path for convering a Float32Array to a
sequence<float> in the DOM bindings at the moment.

-Boris

Rik Cabanier

unread,
Sep 3, 2014, 7:38:29 PM9/3/14
to Boris Zbarsky, blink-dev
On Wed, Sep 3, 2014 at 4:21 PM, Boris Zbarsky <bzba...@mit.edu> wrote:
On 9/3/14, 5:35 PM, Rik Cabanier wrote:
I talked to the mozilla people and this is a bug in the JIT in Firefox
for Windows.
On Mac and Linux, DOMMatrix is actually faster than the JS
implementation with no DOM interaction.

I doubt it's a bug in the JIT.  It's the _native_ version that's slower on Windows, not the JS version!  In any case, it's definitely a Windows-specific issue.

Yeah, I was a bit puzzled about that too when I logged the bug [1] . Maybe Olli misunderstood what code path was slow.
 
I also added tests that use float arrays. They are about the same speed
as DOMMatrix as long as you don't interact with the DOM. As soon as you
cross the DOM, native JS is 4 to 5 times slower than DOMMatrix.

If you pass to a DOM method that expects a sequence<float>, sure: Gecko doesn't have a fast path for convering a Float32Array to a sequence<float> in the DOM bindings at the moment.

I'll update the test so it calls into a real Float32Array method. This should be fast since you can just the pass the raw buffer, correct?

Rik Cabanier

unread,
Sep 3, 2014, 8:11:17 PM9/3/14
to Boris Zbarsky, blink-dev
I updated the float array test so it calls into a WebGL call. [1]

The result is better, but DOMMatrix is now always the fastest. For some reason switching from Float64Array to Float32Array made the calculations slower.

Browser              |  Native  |   JS equivalent  | JS equivalent + DOM access | JS equivalent floatArray |  JS equivalent floatArray + DOM access
Firefox Mac            11.57            10.77                             7.88                         was: 11.78, now: 9.68         was: 3.27, now: 9.11



Adam Barth

unread,
Sep 3, 2014, 8:40:10 PM9/3/14
to Rik Cabanier, Boris Zbarsky, blink-dev
Can you benchmark this in Blink?  Performance numbers from Firefox aren't relevant to deciding how we should structure our implementation.

Rik Cabanier

unread,
Sep 4, 2014, 7:37:30 PM9/4/14
to Adam Barth, Boris Zbarsky, blink-dev
On Wed, Sep 3, 2014 at 5:40 PM, Adam Barth <aba...@chromium.org> wrote:
Can you benchmark this in Blink?  Performance numbers from Firefox aren't relevant to deciding how we should structure our implementation.

Jinho created a private build on ubuntu and ran the performance tests.
Test 7 calculates finite matrices while test 6 runs math on matrices that contain NaNs (This is what caused the regression in Firefox)
Higher numbers are better:
Test: http://jsperf.com/dommatrix-perf/7
TryCount      Native      JS eq      JS eq + DOM      JS eq w/ FA       JS eq w/ FA + DOM
    1                34.25       29.61         13.61                    46.90                       29.89
    2                34.40       29.01         13.16                    46.01                       30.25
    3                34.40       26.97         13.19                    44.04                       30.69

Test: http://jsperf.com/dommatrix-perf/5
TryCount      Native      JS eq      JS eq + DOM      JS eq w/ FA       JS eq w/ FA + DOM
    1               11.02        9.85          5.65                       7.46                        8.70
    2               10.83        9.32          5.51                       7.44                        8.83
    3               11.10       10.40         5.83                       7.34                        8.91

Note that DOMMatrix is the fastest everywhere when there's DOM access.

When just doing the math, the float array implementation is 30% faster. However, the current C++ DOMMatrix always applies the math to a 4x4 matrix, even for the 2D case so there's room for improvement on the C++ side. I believe this is what pdr was concerned about.

Adam Barth

unread,
Sep 4, 2014, 7:50:54 PM9/4/14
to Rik Cabanier, Boris Zbarsky, blink-dev
I'm not sure I understand.  From your table, "JS eq w/ FA" appears to be the fastest at dommatrix-perf/7, which is what I would expect.

I'm not sure I understand how the "+ DOM" condition relates.  You appear to be comparing against the "Native" condition, which doesn't do the same thing (e.g., it's missing the call to gl.uniform2fv).  Wouldn't it be appropriate to compare "JS eq w/ FA + DOM" with "Native + DOM"?

Adam

Adam Barth

unread,
Sep 4, 2014, 7:55:17 PM9/4/14
to Rik Cabanier, Boris Zbarsky, blink-dev
In any case, now we're only talking about 1.3x, which doesn't seem like a big deal.  We need to make the bindings faster so that there's less overhead to leaving the VM, but that work doesn't need to block DOMMatric.

Adam

Rik Cabanier

unread,
Sep 4, 2014, 8:08:56 PM9/4/14
to Adam Barth, Boris Zbarsky, blink-dev
On Thu, Sep 4, 2014 at 4:50 PM, Adam Barth <aba...@chromium.org> wrote:
I'm not sure I understand.  From your table, "JS eq w/ FA" appears to be the fastest at dommatrix-perf/7, which is what I would expect.

I'm not sure I understand how the "+ DOM" condition relates.  You appear to be comparing against the "Native" condition, which doesn't do the same thing (e.g., it's missing the call to gl.uniform2fv).  Wouldn't it be appropriate to compare "JS eq w/ FA + DOM" with "Native + DOM"?

DOMMatrix already lives on the DOM side.
For instance, canvas 2D has the currentTransform attribute [1].
An author could hold on to a reference of that object and use it to change the matrix of the canvas context without making call on the context itself.

I don't think you can do that with a floatarray (but I could be wrong)

Rik Cabanier

unread,
Sep 4, 2014, 8:12:08 PM9/4/14
to Adam Barth, Boris Zbarsky, blink-dev
On Thu, Sep 4, 2014 at 4:55 PM, Adam Barth <aba...@chromium.org> wrote:
In any case, now we're only talking about 1.3x, which doesn't seem like a big deal.  We need to make the bindings faster so that there's less overhead to leaving the VM, but that work doesn't need to block DOMMatric.

Yes, there seems to be a problem on the blink side.
Running this benchmark, Firefox is about 3 times faster which can't be explained by just more efficient matrix math. 

Adam Barth

unread,
Sep 4, 2014, 8:13:10 PM9/4/14
to Rik Cabanier, Boris Zbarsky, blink-dev
We could change the DOM to accept matrices represented in array buffers.  If I were designing the system, that's probably what I would do.

Adam

Jinho Bang

unread,
Sep 4, 2014, 8:43:11 PM9/4/14
to blin...@chromium.org, aba...@chromium.org, bzba...@mit.edu


2014년 9월 5일 금요일 오전 9시 12분 8초 UTC+9, Rik Cabanier 님의 말:



On Thu, Sep 4, 2014 at 4:55 PM, Adam Barth <aba...@chromium.org> wrote:
In any case, now we're only talking about 1.3x, which doesn't seem like a big deal.  We need to make the bindings faster so that there's less overhead to leaving the VM, but that work doesn't need to block DOMMatric.

Yes, there seems to be a problem on the blink side.
Running this benchmark, Firefox is about 3 times faster which can't be explained by just more efficient matrix math. 


I believe Native implementation can be faster than JS implementation(in the jsperf test) because they are not full equivalent.
Actual JS implementation should consider more things such as function overloading, exception handling and so on. therefore it can be slow than now.
However, we still need to improve bindings.

Philip Rogers

unread,
Sep 5, 2014, 6:34:31 PM9/5/14
to Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
Rik,

People in this very thread believe "native is faster" and I couldn't blame someone for using DOMMatrix over glMatrix/Sylvester/etc when we've guided them there with our DOM interfaces. Users will quickly learn they have to write FastDOMMatrix libraries (or add .toDOMMatrix() to existing ones) which makes DOMMatrix little more than a tasty syntax sugar performance trap. The canvas APIs on Android use Matrix; why does ours have to be inferior?


Your DOMMatrix performance numbers look much different than mine.
(Chrome 39.0.2147.0 / OSX with Jinho's rotate patch applied)

Javascript multiplySelf - 72,402,124 ops/s
DOMMatrix multiplySelf - 3,079,299 ops/s

Javascript rotateSelf - 14,340,176 ops/s
DOMMatrix rotateSelf - 1,175,006 ops/s

Javascript translateSelf - 86,842,312 ops/s
DOMMatrix translateSelf - 2,869,811 ops/s

Javascript scaleSelf - 85,933,628 ops/s
DOMMatrix scaleSelf - 2,842,229 ops/s

(these tests technically run two ops per loop)

Elliott Sprehn

unread,
Sep 5, 2014, 7:00:23 PM9/5/14
to Philip Rogers, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
Can the native one use SSE or Neon?

Rik Cabanier

unread,
Sep 5, 2014, 7:03:07 PM9/5/14
to Elliott Sprehn, Philip Rogers, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
On Fri, Sep 5, 2014 at 3:59 PM, Elliott Sprehn <esp...@chromium.org> wrote:
Can the native one use SSE or Neon?

Yes. 
The issue is not the matrix calculations but crossing the C++ layers.
We could add a "combining" API that does executes scale/rotate/translate to mitigate this somewhat.
 

Rik Cabanier

unread,
Sep 5, 2014, 7:36:29 PM9/5/14
to Philip Rogers, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
On Fri, Sep 5, 2014 at 3:34 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

People in this very thread believe "native is faster" and I couldn't blame someone for using DOMMatrix over glMatrix/Sylvester/etc when we've guided them there with our DOM interfaces. Users will quickly learn they have to write FastDOMMatrix libraries (or add .toDOMMatrix() to existing ones) which makes DOMMatrix little more than a tasty syntax sugar performance trap.

The whole point of DOMMatrix is to interact with the object that live on the C++ side. Your tests never cross the boundary so they are not how DOMMatrix would be used in the real world.

Moreover, most (all?) graphics libraries offer a matrix abstraction. It would be terrible if the web platform forces authors to write their own or download additional libraries to handle matrices in SVG, Canvas and CSS. (Rational platform etc)

DOMMatrix does have a conversion method to go to a floatArray but that will likely be slow. Maybe we can provide a get/setFloatArray method?
 
The canvas APIs on Android use Matrix; why does ours have to be inferior?

What canvas API on Android are you referring to? WebGL?
 
Your DOMMatrix performance numbers look much different than mine.
(Chrome 39.0.2147.0 / OSX with Jinho's rotate patch applied)

Javascript multiplySelf - 72,402,124 ops/s
DOMMatrix multiplySelf - 3,079,299 ops/s

Javascript rotateSelf - 14,340,176 ops/s
DOMMatrix rotateSelf - 1,175,006 ops/s

Javascript translateSelf - 86,842,312 ops/s
DOMMatrix translateSelf - 2,869,811 ops/s

Javascript scaleSelf - 85,933,628 ops/s
DOMMatrix scaleSelf - 2,842,229 ops/s

(these tests technically run two ops per loop)

You're basically testing DOM performance. What happens if you try to use those matrices?
 
On Thu, Sep 4, 2014 at 5:43 PM, Jinho Bang <jinho...@samsung.com> wrote:


2014년 9월 5일 금요일 오전 9시 12분 8초 UTC+9, Rik Cabanier 님의 말:



On Thu, Sep 4, 2014 at 4:55 PM, Adam Barth <aba...@chromium.org> wrote:
In any case, now we're only talking about 1.3x, which doesn't seem like a big deal.  We need to make the bindings faster so that there's less overhead to leaving the VM, but that work doesn't need to block DOMMatric.

Yes, there seems to be a problem on the blink side.
Running this benchmark, Firefox is about 3 times faster which can't be explained by just more efficient matrix math. 


I believe Native implementation can be faster than JS implementation(in the jsperf test) because they are not full equivalent.
Actual JS implementation should consider more things such as function overloading, exception handling and so on. therefore it can be slow than now.
However, we still need to improve bindings.

Philip Rogers

unread,
Sep 5, 2014, 10:29:18 PM9/5/14
to Rik Cabanier, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
Rik,

It may have gotten lost in all of my complaining, but I do support these interfaces in general. My issue is only with the performance in implementations.

Now, back to your regularly scheduled complaining.. Responses in-line below.

On Fri, Sep 5, 2014 at 4:36 PM, Rik Cabanier <caba...@gmail.com> wrote:



On Fri, Sep 5, 2014 at 3:34 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

People in this very thread believe "native is faster" and I couldn't blame someone for using DOMMatrix over glMatrix/Sylvester/etc when we've guided them there with our DOM interfaces. Users will quickly learn they have to write FastDOMMatrix libraries (or add .toDOMMatrix() to existing ones) which makes DOMMatrix little more than a tasty syntax sugar performance trap.

The whole point of DOMMatrix is to interact with the object that live on the C++ side. Your tests never cross the boundary so they are not how DOMMatrix would be used in the real world.


DOMMatrix is going to be used as more than just an interface with the DOM. DOMMatrix appears across our graphics APIs (canvas, svg, etc). If you were new to javascript, it would be natural for you to use the same matrix class for everything.

Imagine you are a Java developer bringing a graphics application over to the web. How are you supposed to know that you should use DOMMatrix for setting the transform on your 2d canvas context, but not for filtering each pixel?

 

Moreover, most (all?) graphics libraries offer a matrix abstraction. It would be terrible if the web platform forces authors to write their own or download additional libraries to handle matrices in SVG, Canvas and CSS. (Rational platform etc)


Exactly! What other platform puts an extra slow matrix class on their APIs? Android has Matrix which is used directly with Canvas.

 

DOMMatrix does have a conversion method to go to a floatArray but that will likely be slow. Maybe we can provide a get/setFloatArray method?
 
The canvas APIs on Android use Matrix; why does ours have to be inferior?

What canvas API on Android are you referring to? WebGL?
 
Your DOMMatrix performance numbers look much different than mine.
(Chrome 39.0.2147.0 / OSX with Jinho's rotate patch applied)

Javascript multiplySelf - 72,402,124 ops/s
DOMMatrix multiplySelf - 3,079,299 ops/s

Javascript rotateSelf - 14,340,176 ops/s
DOMMatrix rotateSelf - 1,175,006 ops/s

Javascript translateSelf - 86,842,312 ops/s
DOMMatrix translateSelf - 2,869,811 ops/s

Javascript scaleSelf - 85,933,628 ops/s
DOMMatrix scaleSelf - 2,842,229 ops/s

(these tests technically run two ops per loop)

You're basically testing DOM performance. What happens if you try to use those matrices?


I don't understand this argument. The expensive parts of this interface in both Chromium and Webkit are the bindings. Only DOMMatrix requires that you cross this layer for regular math operations too. Is context.setTransform(DOMMatrix) faster than context.setTransform(Float32Array)?

Rik Cabanier

unread,
Oct 27, 2014, 5:31:03 PM10/27/14
to Philip Rogers, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
On Fri, Sep 5, 2014 at 7:28 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

It may have gotten lost in all of my complaining, but I do support these interfaces in general. My issue is only with the performance in implementations.

Picking this up again.
Do you have a counter proposal on how this could be implemented better?

Philip Rogers

unread,
Oct 27, 2014, 5:34:17 PM10/27/14
to Rik Cabanier, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
Rik,

Yes, an alternative is to implement and standardize these interfaces as first-class citizens in Ecmascript.

Domenic Denicola

unread,
Oct 27, 2014, 5:41:09 PM10/27/14
to Philip Rogers, Rik Cabanier, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
From: p...@google.com [mailto:p...@google.com] On Behalf Of Philip Rogers

> Yes, an alternative is to implement and standardize these interfaces as first-class citizens in Ecmascript.

Why is the standards body where the work gets done relevant to how these interfaces perform in Chrome?

Is this actually a technical issue, of whether they should be implemented in V8 or in Blink? If so, I'll note we had a similar discussion earlier with Streams.

In general it would be good to have a plan for implementing web features "in V8." (More likely: we'd want to implement features like this using the same self-hosting mechanisms we would use while implementing built-ins in V8, but without actually perturbing the V8 code base.)

Rik Cabanier

unread,
Oct 27, 2014, 5:41:53 PM10/27/14
to Philip Rogers, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
On Mon, Oct 27, 2014 at 2:33 PM, Philip Rogers <p...@chromium.org> wrote:
Rik,

Yes, an alternative is to implement and standardize these interfaces as first-class citizens in Ecmascript.

I don't understand how this would be a solution.
Yes, just doing the manipulation just on the JS side would be faster, but the C++ side that has to observe these values would become much slower. This slowdown would happen even if you make no change.
Could you elaborate how the bindings would look? Someone proposed this for Firefox and bz had the same concern [1]

Boris Zbarsky

unread,
Oct 27, 2014, 5:45:43 PM10/27/14
to Rik Cabanier, Philip Rogers, Jinho Bang, blink-dev, Adam Barth
On 10/27/14, 5:41 PM, Rik Cabanier wrote:
> Could you elaborate how the bindings would look? Someone proposed this
> for Firefox and bz had the same concern [1]

That was a different concern. That proposal was more akin to the way
Blink-in-JS works, which involves going from JS into C++ and back out
into JS running in a different security context.

-Boris

Philip Rogers

unread,
Oct 27, 2014, 5:46:19 PM10/27/14
to Domenic Denicola, Rik Cabanier, Jinho Bang, blink-dev, Adam Barth, Boris Zbarsky
Domenic,

Yeah, I was jumping ahead a bit there. Implementing DOMMatrix "in V8" is all I intended. I agree that it would be good to figure out how to do these in general.

Philip Rogers

unread,
Oct 27, 2014, 5:53:01 PM10/27/14