From a post on pushing large byte arrays between JS and elm:
I recently benchmarked the various options (thank you BrianHicks/elm-benchmark!). To summarize, if you want to get an array of numbers from Elm into JS, and you use Array.Hamt as your Array type in 0.18, you can’t do the obvious:
import Array.Hamt as Array
port sendAllTheInts : Array Int -> Cmd msg
This fails because there is no native support for Array.Hamt in port marshaling. (Aside, if Json.Encode were a typeclass, then Array.Hamt could have provided an implementation …).
The next obvious approach is:
import Array.Hamt as Array
sendAllTheInts : Array Int -> Cmd msg
sendAllTheInts = Array.toList >> sendAllTheInts_
port sendAllTheInts_ : List Int -> Cmd msg
But this is slower than this:
import Array.Hamt as Array
import Json.Encode as E
sendAllTheInts : Array Int -> Cmd msg
sendAllTheInts = Array.map E.int >> Array.toList >> E.list >> sendAllTheInts_
port sendAllTheInts_ : E.Value -> Cmd msg
Nice thing is that the slippery E.Value argument to the port is hidden within your module (don’t expose sendAllTheInts_). And, bonus, the JS code is exactly the same (save the name of the port) in all three cases!
I tried writing an Array.Hamt to Array conversion function, and so the port could marshal a native Array… but that was slower than the List based versions above.