Harbs,

I feel like several independent factors are being mixed together.  I think
it is better to address them separately.

Also, IMO, there are two kinds of layout in Royale.  One group of layouts
just lets the browser do the layout, like VerticalLayout, HorizontalLayout
and the Layouts that use FlexBox.  The other group of layouts tries to run
code to solve layout issues that browsers don't make easy or to emulate
Apache Flex behavior.  This is things like VerticalColumnLayout,
VerticalLayoutWithPaddingAndGap, and the FlexibleChild layouts, and some
custom layouts like NumericStepper and the ProductsView layout in
RoyaleStore example.

When we first started out on FlexJS/Royale six years ago, the only browser
layouts I knew about were setting the display style to "blocK" or
"inline-block" to get vertical or horizontal layout.  So we used it where
we could and wrote other custom layouts to handle other cases in the
second group.  Over time, new display styles have emerged as useful and
stable.  Mainly display="flex" a couple of years ago and now/soon
display="grid".  Slowly but surely, the browsers are solving the pain
points folks used to workaround.

I agree with Carlos that we really want the browser to run its layout code
instead of us running our layout code where possible.

So given all that, I think the independent issues are:
1) can we optimize our layouts to use browser layouts more?
2) can we optimize our layouts to avoid direct interactions with the dom?
3) is there any advantage to deferring layout via requestanimationframe?

For example, it may be that VerticalColumnLayout should just use CSSGrid
or FlexBox.  It may be that VerticalLayoutWithPaddingAndGap should just
set margins on all of its children.  It could be that there is a CSS way
to layout NumericStepper that we don't have to run any code to measure and
compute sizes.

I see you pushed some optimizations that cache values read from the DOM.
That's definitely worth doing no matter what we decide about #3.

For #3, as you mentioned, there are risks about things getting out of
sync.  It isn't clear to me that requestAnimationFrame is special in that
DOM write/read is some how more efficient in when run in the animation
frame instead of in regular code.  If you need to change something and
respond to its new computed value, I think you will simply have to pay the
price of computing that value.  And debugging callbacks can be painful as
well.

For me, #3 is the main point of concern.  I don't see how it should be
used in the core when doing #1 and #2 should be sufficient because it is
more straight forward changes and more PAYG.  I would like to see how far
you can get by first refactoring things to use #1 and #2, then see what
the tradeoffs are on #3.  requestAnimationFrame probably can be useful for
some layouts in Royale, but I don't believe it will benefit all layouts.
But revisiting our existing layouts to use #1 and #2 will benefit a lot
more of our layouts.

Ideally, folks will use Royale to create exactly the same DOM they would
if they had written the HTML by hand.  I could be wrong, but I believe
there are tons of apps out there with very little or no custom layout code
that reads the DOM and writes new values.  The app sets CSS and relies
completely on the browser.  New Royale users should be able to write such
apps and won't need deferred layout.  Migrating customers may use
emulation components and layout that cannot use the browser because Flex
used CSS is a non-compliant way, but over time, even those folks may
migrate away from the emulation components into UI that leverages the
browser.  Eventually, as browsers agree on how to  solve other common
layout hassles, fewer of Royale layouts will need to run custom code.

It may be that for now, we should create a CustomLayoutBase that extends
LayoutBase and moves the width/height caching from LayoutBase to
CustomLayoutBase so that the first group of layouts can extend LayoutBase
and the second group extend CustomLayoutBase and pick up width/height
caching.  But I expect that over time, the number of CustomLayoutBases
will dwindle as browsers agree on ways to implement what those custom
layouts do.

My 2 cents,
-Alex

On 3/26/18, 9:21 AM, "Harbs" <[email protected]> wrote:

>Hi Carlos,
>
>There’s one thing to consider here which is really important in my
>opinion:
>
>All the major frameworks (i.e. React, Vue, etc.) have Virtual DOM
>optimizations because direct interactions with the DOM (be it elements or
>CSS) is painfully slow. This is true for both reads and writes. Mixing
>reads and writes is even worse, because it forces reflow, but even
>without forced reflow, the more interaction with the DOM, the slower your
>app will be.
>
>Royale has a huge advantage over the other frameworks because they need
>to use diffing to sync their virtual DOM with the real DOM. In Royale, we
>wrap the real DOM in our components which can act as a “wrapper” virtual
>DOM. We don’t need diffing and we don’t need to find the DOM elements in
>the tree (which can cause more performance problems) because we have
>direct references to the actual DOM element.
>
>When necessary, we can and should access the DOM element to write and
>read what we need, but we should identify performance bottlenecks where
>we should avoid accessing the DOM elements directly when possible. x, y,
>width and height are four areas which my tests have shown huge
>differences by avoiding direct DOM interactions. My optimizations have
>reduced the rendering time of the RoyaleStore app starting from the
>Application.start() until the rendering finished from 340 ms down to 220
>ms. This is mostly due to removing layout thrashing and avoiding direct
>access of x, y, width and height.
>
>I think there’s a lot more work to do in this area, but I think we should
>be abstracting more of the DOM away and not less…
>
>My $0.02,
>Harbs
>
>> On Mar 26, 2018, at 6:51 PM, Carlos Rovira <[email protected]>
>>wrote:
>> 
>> Hi,
>> 
>> just get the time to read the whole thread and now I want to say some
>> things.
>> 
>> First, Harbs, thanks for working on this. I think this topic is super
>> important since if we don't get smooth apps in desktop and mobile, we're
>> losing our time here, since nobody will use Royale in the end. So Layout
>> performance is critical.
>> 
>> Then, most of us are working with little example apps, or most complex
>> royale examples actually are not using resizings and other layout
>>changes,
>> so is difficult to measure how is the actual way of doing things. The
>>only
>> reference I have is with Harbs app posted several months ago. In that
>>case,
>> in desktop performs ok, but trying in mobile (and considering it wasn't
>> optimized for mobiles and tablets), the performance was not good. I
>>assume
>> the problem was multiple: at that time Flexjs still more alpha than
>>Royale
>> now, a first huge app, no optimizations in framework and the app, and
>>maybe
>> created at that time with desktop in mind (no mobile devices).
>> So it's clear that we need optimization, and as well Harbs created the
>>app
>> with a way to solve the problems he had with the current tools he had at
>> the moment and maybe that's the best way. Don't know since I don't know
>>how
>> that Code is done.
>> 
>> In the other hand, I'm a huge advocate of some of the things Alex said
>> below. The way I see Royale is as a way to encapsulate common patterns
>>and
>> to get the best more simple DOM possible that works better. And for me
>>is
>> DOM combined with CSS.
>> 
>> In the example posted by Alex:
>> 
>> <body>
>>  <div>
>>    <span style="display:block">type below...</span>
>>    <input />
>>  </div>
>> </body>
>> 
>> I agree with in all that output but not in the style attribute for me it
>> should be remove and have a css rule that setup the display:block for
>>the
>> span.
>> 
>> So we don't need to follow exactly what Flex did. In fact we're changing
>> lots of things for Royale, like introducing strands/beads, and many
>>other
>> things.
>> 
>> For that reason things like LAYOUTS, TRANSITIONS and STYLES are
>>something
>> that the browser puts in CSS and we should do the same. In other words:
>>I'm
>> confident that browser vendors optimize how HTML, CSS and JS renders and
>> works between them. So this means again that our mission is to create
>>the
>> best, optimal and simple HTML/CSS/JS we can. That's the power we can
>> provide to our users, and we must trust in how browsers will perform
>>since
>> they are responsible of the rendering engine.
>> 
>> So in the we shouldn't do much code, checking, loops, and more and
>>should
>> trust more in media-queries css rules and attributes and so.
>> 
>> For example, for responsiveness we should not have any code in a
>>layout, we
>> should introduce a CSS media-query that will be responsible of change
>>the
>> rendering as the user executes the app in desktop, mobile or tablet.
>> 
>> That's the same reason why I try to remove in Jewel all "style"
>>attributes
>> in components and making that components to have the same information in
>> it's own css rule attribute set as a class, since we see in all browser
>> apps out there written in other popular frameworks that's a good
>>practice
>> and encourages separation of concerns while it should perform right
>>since
>> browser vendors are optimizing that. So for me, a concrete component has
>> CSS rules that sets display to block, inline-block, ... or position to
>> absolute or relative and more, and I think that's the same for
>>transitions.
>> I don't expect to write transition javascript code, since I expect to
>>setup
>> in AS3/MXML and that code implies to assign a css rule that set up the
>> standard CSS transition code.
>> 
>> So returning to royale, I think we'll gain the performance battle if we
>>can
>> make royale to write apps that :
>> 
>> - uses HTML to declare components (with attributes), "layouts"(that's
>>the
>> divs that holds other comps), and maybe no more
>> - uses CSS to declare display, layout, transition, styles (colors,
>> lines,...) since that's its responsibility
>> - uses JS to make code, but not whatever code!, just the one that is
>>needed
>> for the app and to "bind" things together.
>> 
>> For example, we should ask ourselves if width, explicitWidth should be
>> delegated to CSS since is where sizes are better handled.Maybe we are
>> trying to do that in JS, and maybe that's not the actual way of doing
>> things out there. So we should not try to force the browsers to do
>>things
>> they are not prepared to.
>> 
>> That's the way I see this, regarding HTML output. SWF is another beast
>>that
>> should be covered as well to see how to become part of all of this.
>> 
>> My 2ctns! :)
>> 
>> Carlos
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 2018-03-26 14:43 GMT+02:00 Harbs <[email protected]>:
>> 
>>> Another bottleneck I’ve observed is the use of Language.is and
>>> Language.as. Each call is pretty cheap, but they all add up —
>>>especially
>>> calls which use interfaces.
>>> 
>>>> On Mar 26, 2018, at 3:37 PM, Harbs <[email protected]> wrote:
>>>> 
>>>> I managed to more or less double the performance on this…
>>>> 
>>>>> On Mar 26, 2018, at 1:21 PM, Harbs <[email protected] <mailto:
>>> [email protected]>> wrote:
>>>>> 
>>>>> Another interesting study is NumericStepperView. NumericStepperView
>>> strand setter takes 12.6 ms to run on a single component! There are
>>>many
>>> subsequent DOM read and writes in that component causing it to take
>>>much
>>> longer than necessary to render. I’m going to make some changes to the
>>> class which should vastly improve performance on that.
>>>>> 
>>>> 
>>> 
>>> 
>> 
>> 
>> -- 
>> Carlos Rovira
>> 
>>https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fabout.me%
>>2Fcarlosrovira&data=02%7C01%7Caharui%40adobe.com%7Ceb3d99ca0c274770641908
>>d59335b768%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C63657678128014394
>>9&sdata=cGtXQXxJlF1HJnlxrbunL4HvmFS0%2F%2Bik8i6wNxF0mrc%3D&reserved=0
>

Reply via email to