Skip to content

Commit

Permalink
Optimize compiler code to reduce compile times
Browse files Browse the repository at this point in the history
Refactor the implementation of the Elm compiler in various places to reduce memory allocations and transformation steps during compilation.
  • Loading branch information
Viir committed Jan 2, 2024
1 parent 9f173f8 commit e607d5d
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 207 deletions.
100 changes: 44 additions & 56 deletions implement/elm-time/ElmTime/compile-elm-program/src/ElmInteractive.elm
Original file line number Diff line number Diff line change
Expand Up @@ -707,51 +707,34 @@ compilationAndEmitStackFromInteractiveEnvironment environmentDeclarations =
json_encode_pineValue : Dict.Dict String Pine.Value -> Pine.Value -> Json.Encode.Value
json_encode_pineValue dictionary value =
let
blobDict =
dictionary
|> Dict.toList
|> List.filterMap
(\( entryName, entryValue ) ->
case entryValue of
Pine.BlobValue blob ->
Just ( blob, entryName )

_ ->
Nothing
)
|> Dict.fromList

listDict =
dictionary
|> Dict.toList
|> List.filterMap
(\( entryName, entryValue ) ->
case entryValue of
Pine.ListValue list ->
Just ( list, entryName )
dicts =
Dict.foldl
(\entryName entryValue aggregate ->
case entryValue of
Pine.BlobValue blob ->
{ aggregate
| blobDict = Dict.insert blob entryName aggregate.blobDict
}

Pine.ListValue list ->
let
hash =
pineListValueFastHash list

_ ->
Nothing
)
|> List.foldl
(\( nextList, nextName ) intermediateDict ->
let
hash =
pineListValueFastHash nextList

assocList =
intermediateDict
|> Dict.get hash
|> Maybe.withDefault []
|> (::) ( nextList, nextName )
in
intermediateDict
|> Dict.insert hash assocList
)
Dict.empty
assocList =
Dict.get hash aggregate.listDict
|> Maybe.withDefault []
|> (::) ( list, entryName )
in
{ aggregate
| listDict = Dict.insert hash assocList aggregate.listDict
}
)
{ blobDict = Dict.empty, listDict = Dict.empty }
dictionary
in
json_encode_pineValue_Internal
{ blobDict = blobDict, listDict = listDict }
dicts
value


Expand Down Expand Up @@ -971,20 +954,25 @@ json_decode_pineValueGeneric config =

pineListValueFastHash : List Pine.Value -> Int
pineListValueFastHash list =
list
|> List.indexedMap
(\index entry ->
(case entry of
Pine.BlobValue blob ->
71 * List.length blob

Pine.ListValue innerList ->
7919 * List.length innerList
)
* (index + 1)
)
|> List.sum
|> (+) (List.length list)
let
calculateEntryHash : Pine.Value -> Int
calculateEntryHash entry =
case entry of
Pine.BlobValue blob ->
71 * List.length blob

Pine.ListValue innerList ->
7919 * List.length innerList
in
case list of
[] ->
8831

[ entry ] ->
calculateEntryHash entry * 31

entry1 :: entry2 :: _ ->
calculateEntryHash entry1 * 41 + calculateEntryHash entry2 * 47 + List.length list


json_decode_optionalNullableField : String -> Json.Decode.Decoder a -> Json.Decode.Decoder (Maybe a)
Expand Down
19 changes: 9 additions & 10 deletions implement/elm-time/ElmTime/compile-elm-program/src/FirCompiler.elm
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,18 @@ emitExpressionInDeclarationBlock stackBeforeAddingDeps blockDeclarations mainExp
importedModulesDeclarationsFlat : Dict.Dict String Expression
importedModulesDeclarationsFlat =
stackBeforeAddingDeps.moduleImports.importedModules
|> Dict.toList
|> List.concatMap
(\( moduleName, importedModule ) ->
|> Dict.foldl
(\moduleName importedModule aggregate ->
importedModule.declarations
|> Dict.toList
|> List.map
(\( declName, declValue ) ->
( String.join "." (moduleName ++ [ declName ])
, LiteralExpression declValue
)
|> Dict.foldl
(\declName declValue ->
Dict.insert
(String.join "." (moduleName ++ [ declName ]))
(LiteralExpression declValue)
)
aggregate
)
|> Dict.fromList
Dict.empty

importedDeclarations : Dict.Dict String Expression
importedDeclarations =
Expand Down
90 changes: 90 additions & 0 deletions implement/elm-time/ElmTime/compile-elm-program/src/Hex.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
module Hex exposing (..)

{-| Convert a decimal integer to a hexdecimal string such as `"abc94f"`.
Hex.toString 165 == "a5"
-}


toString : Int -> String
toString num =
String.fromList
(if num < 0 then
'-' :: unsafePositiveToDigits [] (negate num)

else
unsafePositiveToDigits [] num
)


{-| ONLY EVER CALL THIS WITH POSITIVE INTEGERS!
-}
unsafePositiveToDigits : List Char -> Int -> List Char
unsafePositiveToDigits digits num =
if num < 16 then
unsafeToDigit num :: digits

else
unsafePositiveToDigits (unsafeToDigit (modBy 16 num) :: digits) (num // 16)


{-| ONLY EVER CALL THIS WITH INTEGERS BETWEEN 0 and 15!
-}
unsafeToDigit : Int -> Char
unsafeToDigit num =
case num of
0 ->
'0'

1 ->
'1'

2 ->
'2'

3 ->
'3'

4 ->
'4'

5 ->
'5'

6 ->
'6'

7 ->
'7'

8 ->
'8'

9 ->
'9'

10 ->
'a'

11 ->
'b'

12 ->
'c'

13 ->
'd'

14 ->
'e'

15 ->
'f'

_ ->
-- if this ever gets called with a number over 15, it will never
-- terminate! If that happens, debug further by uncommenting this:
--
-- Debug.todo ("Tried to convert " ++ toString num ++ " to hexadecimal.")
unsafeToDigit num
Loading

0 comments on commit e607d5d

Please sign in to comment.