avh4 / elm-color

Standard representation of colors, encouraging sharing between packages. (This replaces elm-lang/core#Color from Elm 0.18.)
BSD 3-Clause "New" or "Revised" License
23 stars 6 forks source link

200% speed increase for toCssString #22

Closed folkertdev closed 4 years ago

folkertdev commented 4 years ago

By using ++ instead of String.concat, converting to a css string is about 200% faster. The reason is list allocation and traversal, which isn't needed here. I think the code quality does not suffer.

The conversion of colors to strings took about 6% of total time for some svg animations. It's not a big deal, but an easy gain with benefits for all depending libraries, in this case typed svg.

Benchmarking code used

module RunBenchmark exposing (main)

import Benchmark exposing (..)
import Benchmark.Runner exposing (BenchmarkProgram, program)

main : BenchmarkProgram
main =
    program suite

suite : Benchmark
suite =
    describe "Array"
        [ -- nest as many descriptions as you like
          describe "slice"
            [ Benchmark.compare "from the beginning"
                "old"
                (\_ -> toCssString 0.7 0.3 0.1 0.9)
                "new"
                (\_ -> toCssStringNew 0.7 0.3 0.1 0.9)
            ]
        ]

toCssString : Float -> Float -> Float -> Float -> String
toCssString r g b a =
    let
        pct x =
            ((x * 10000) |> round |> toFloat) / 100

        roundTo x =
            ((x * 1000) |> round |> toFloat) / 1000
    in
    String.concat
        [ "rgba("
        , String.fromFloat (pct r)
        , "%,"
        , String.fromFloat (pct g)
        , "%,"
        , String.fromFloat (pct b)
        , "%,"
        , String.fromFloat (roundTo a)
        , ")"
        ]

toCssStringNew : Float -> Float -> Float -> Float -> String
toCssStringNew r g b a =
    let
        pct x =
            ((x * 10000) |> round |> toFloat) / 100

        roundTo x =
            ((x * 1000) |> round |> toFloat) / 1000
    in
    "rgba("
        ++ String.fromFloat (pct r)
        ++ "%,"
        ++ String.fromFloat (pct g)
        ++ "%,"
        ++ String.fromFloat (pct b)
        ++ "%,"
        ++ String.fromFloat (roundTo a)
        ++ ")"
avh4 commented 4 years ago

Sorry for the slow reply here. Thanks for investigating and giving the detailed explanation!