Elm-UI performance issues on older devices

Hi All!

We recently stumbled on some css issues with our handwritten css sheet (cross platform layout issues etc.).
So I wanted to give Elm-UI a try. I have converted pieces of the code to use Elm-UI. It’s a simple webapp to control a device. It currently shows a few buttons in the header, together with a logo and two tabs. When switching between the two tabs, only the dynamic style sheet is updated (verified with Chrome). The background color and the text color is changed to highlight the selected tab.

When I run the app and switch between tabs on a PC or new tablet, it runs smoothly but when I run it on a iPhone or Android of +2 years old it doesn’t feel responsive any more. The tab switching is very slow.

As we are using Elm for the webapp from start with a static style sheet I know what kind of responsiveness I should expect. It seems to me that Elm-UI requires quite some processing power.

Any ideas on how I can improve this? I saw an option to have noStaticStyleSheet, is there maybe a way to only have a static style sheet?

I’m not using Lazy at this stage as I do not fully understand it yet.
But as far as I understand, it will only enhance performance if limited changes happen. So if I would switch from the controlling panel to for example the settings or login panel, the generation of the style sheet would still be slow.

Thanks for taking the time!

Kind regards,
Jasper

You didn’t have a touch-action: manipulation in your CSS that you removed accidentally (or <meta name="viewport" content="width=device-width">) that would lead to a tap delay ?

We did not use touch-action: manipulation before but we use the meta tag: <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
It’s in index.html which did not change.

Ok. Then how are you selecting the current tab view? Maybe you are computing all tabs views and display only one? I have seen this and this would penalize the performance more with elm-ui (like using viewIf instead of viewIfLazy with elm/html).

A code sample/example could help.

Please find the full view below:

view : Model -> Html Msg
view model =
  Element.layoutWith
    { options =
        [ Element.focusStyle
            { borderColor = Nothing
            , backgroundColor = Nothing
            , shadow = Just
               { color = focusShadowColor model.theme
                , offset = (0, 0)
                , blur = 3
                , size = 2
               }
            }
        , Element.noHover
        ]
    }
    [ Background.color (backgroundColor model.theme) ]
    ( case model.activePanel of
        ControlPanel  -> viewControlPanel model
        SettingsPanel -> viewLoginPanel model
        LoginPanel    -> viewLoginPanel model
    )


--------------------------------------------------------------------------------
-- VIEW CONTROL PANEL

viewControlPanel : Model -> Element.Element Msg
viewControlPanel model =
  let
    viewZoneTabsAndSelectedZone =
      Element.column
        [ Element.height (Element.fillPortion 25)
        , Element.width Element.fill
        ]
       [ viewZoneTabs model
        , viewSelectedZone model
        ]
  in
    Element.column
      [ Element.width Element.fill
      , Element.height Element.fill
      ]
      [ viewControlPanelHeader model.theme
      , viewZoneTabsAndSelectedZone
      ]

-- ZONE TABS
viewZoneTabs : Model -> Element.Element Msg
viewZoneTabs model =
  let
    viewZoneName zone =
     Element.el
        [ Element.centerX
        , Font.color
            ( if ( model.selectedZoneId == zone.id ) then
               fontColorSelectedZone model.theme
             else
                white
            )
        , Font.size 14
        , Font.family
            [ Font.typeface "Frutiger55RomanBold"
            , Font.sansSerif
            ]
        ]
        ( Element.text (String.toUpper zone.name) )

viewZoneSCLed zone =
  Element.el
    [ Element.centerX
    , Element.width (Element.px 8)
    , Element.height (Element.px 8)
    , Border.rounded 4
    , Background.color (getSCLedColor zone.signal zone.clip)
    ]
    ( Element.none )

viewZoneTab : Zone -> Element.Element Msg
viewZoneTab zone =
  Element.column
    [ Element.width Element.fill
    , Element.alignBottom
    , Element.spacing 10
    , Element.paddingXY 0 8
    , Background.color
        ( if ( model.selectedZoneId == zone.id ) then
            backgroundColorSelectedZone model.theme
          else
            greyI
        )
    , Border.roundEach
        { topLeft = 10
        , topRight = 10
        , bottomLeft = 0
        , bottomRight = 0
        }
    , Events.onClick (SwitchZone zone.id)
    ]
    [ viewZoneSCLed zone
    , viewZoneName zone
    ]
  in
    Element.row
      [ Element.height (Element.fillPortion 1)
      , Element.width Element.fill
      , Element.paddingXY 10 0
      , Background.color greyI
      ]
      [ viewZoneTab model.zone1
      , viewZoneTab model.zone2
      ]

-- SELECTED ZONE
viewSelectedZone : Model -> Element.Element Msg
viewSelectedZone model =

    Element.el
      [ Element.height (Element.fillPortion 35) ]
      (Element.none)

Does your viewSelectedZone function really display only Element.none? Maybe worth setting-up an Ellie example too to analyze.

At this stage it does, I’m converting piece by piece. Currently viewSelectedZone is just a place holder. It will show some controls later on (volume, selection,…).

I’ll look into Ellie :slight_smile:.

I’m not able to share the full code on Ellie as this is proprietary information. Which information apart from the above would you like to have?

Some questions that popped into my head:
I’m wondering how Lazy could help me here (if it can)?
What debug tools can I use to give a better overview of what is happening (preferable with some Elm knowledge)?
Is this problem more related to how I use Elm-UI or is it a property of Elm-UI?
Did someone else experience similar behavior?
Is there a way to create static style sheets with Elm-UI so I can verify that it is indeed the creation of the style sheet that is “slow”?

Thanks a lot!

Never mind the question about Lazy. Documentation is quite clear (https://guide.elm-lang.org/optimization/lazy.html).

In Chrome I would use the developer tools ‘Performance’ tab. Start recording, perform some UI actions, then drill down the results and see how long screen renders are taking.

Perhaps as you are running on older hand-held devices you don’t have Chrome developer tools? You could still run on a desktop machine comparing your static CSS site with the elm-ui one to get an idea of how the performance differs.

Comparing them gives me some insight indeed. I changed the Elm code of the handwritten css version so it also leaves the viewSelectedZone empty. Both pages look similar now.

I recorded and then changed the selected zone. Following happens:

events handwritten css Elm-UI
event is triggered 1.02 ms 0.68 ms (x 0.67)
animation frames fired 2.3 ms 2.5 ms (x 1.08)
recalculate style 0.56 ms 1.36 ms (x 2.43)
update layer tree 0.26 ms 0.07 ms (x 0.27)
paint 0.22 ms 0.23 ms (x 1.05)
composite layers 0.21 ms 0.18 ms (x 0.86)

Some take longer, some are shorter. The difference in the event time is due to the different event handler used I believe. The biggest difference can be seen in the recalculate style event.

I would like to use web inspector on my iPhone to inspect the performance there but it seems that you need a mac for that…

1 Like

Looking at those numbers it isn’t really screaming out that elm-ui is any slower. Faster in many cases.

I notice that ‘composite layers’ has some time allocated to it. I have run into performance issues with compositing - in my case on Linux boxes which don’t always have GPU configured correctly for Chrome. Just a guess, but is this an area worth looking into?

I made this naive performance test to track down similar problems on iPhone 9. It makes it easy to compare the performance on different devices.

Sorry for bothering you all.
It looked like it was Elm-UI related but it wasn’t. I connected a macbook Air to it and during analyzing with web inspector I noticed that there is a difference between normal safari or the webapp in home screen mode. So the poor performance of the Elm-UI version was only in home screen mode.

Apparently this is solved in newer iOS versions so I updated from iOS10 to 12 and do not have the issue any more! This is probably due to the 300ms tap delay as mentioned by dmy. Apple didn’t solve that issue for home screen webapps, only in safari.

Strange enough it does not have the slower performance for the handwritten css version. That is why I thought it was Elm-UI related.

I’m happy it’s solved :slight_smile: as I can now continue using Elm-UI.

Thanks any way for the help, really appreciate it!

4 Likes

I believe old iOS home web apps used the webview without the JS JIT. I think only in the last versions they enabled the wkwebview on those apps and also on third party browser apps.

That could be the reason for the degraded performance that you weren’t seeing with the CSS version.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.