How can I pass around state without copying an entire structure per message?

Viewed 125

I have a textbox that's extremely slow when displaying characters.

I once observed a Stackoverflow exception related to it.

I believe that the performance issue is associated to preparing the portal value:

Sources.InputAccessId _ ->
    ( { model | portal = portal }, sourceCmd )

Each time a character is keyed-in, I copy and modify a new portal record which consumes more memory.

The code can be found below.

Main:

onSourcesUpdated : Sources.Msg -> Model -> ( Model, Cmd Msg )
onSourcesUpdated subMsg model =
    let
        pendingPortal =
            model.portal

        provider =
            pendingPortal.provider

        profile =
            provider.profile

        source =
            pendingPortal.newSource

        ( sources, subCmd ) =
            Sources.update subMsg
                { profileId = profile.id
                , platforms = model.platforms
                , source = { source | profileId = profile.id }
                , sources = profile.sources
                }

        sourceCmd =
            Cmd.map SourcesUpdated subCmd

        pendingProvider =
            { provider | profile = { profile | sources = sources.sources } }

        portal =
            { pendingPortal | newSource = sources.source, provider = pendingProvider }
    in
        case subMsg of
            Sources.InputAccessId _ ->
                ( { model | portal = portal }, sourceCmd )
            ...

Sources.elm:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    let
        source =
            model.source
    in
        case msg of
            InputAccessId v ->
                ( { model | source = { source | accessId = v } }, Cmd.none )
    ...

How can I pass around state without copying entire structures each time an event occurs?

1 Answers

You might want to debounce these events with libraries like this one: elm-debounce

The consequence of debouncing though is that some events will be discarded so you only get one that sums them all when the user is done typing/interacting with the page (more precisely, after a – configurable - timeout).

Related