Skip to content

Commit

Permalink
Rewrite for efficiency - partitioning into recursion domains
Browse files Browse the repository at this point in the history
Find a more efficient algorithm to compose the list of recursion domains when compiling an Elm module. Following this change, we observed savings of circa 30 percent in the total number of performed instructions/invocations in the scenario compiling all Elm compiler modules.
  • Loading branch information
Viir committed Aug 2, 2024
1 parent 403611e commit fb76785
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 61 deletions.
6 changes: 3 additions & 3 deletions implement/Pine.Core/Pine.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<AssemblyVersion>0.3.14</AssemblyVersion>
<FileVersion>0.3.14</FileVersion>
<AssemblyVersion>0.3.15</AssemblyVersion>
<FileVersion>0.3.15</FileVersion>
</PropertyGroup>

<PropertyGroup>
<PackageId>Pine.Core</PackageId>
<Version>0.3.14</Version>
<Version>0.3.15</Version>
<Description>The cross-platform Elm runtime environment</Description>
<PackageTags>Functional;Elm;Runtime;Compiler;VM;DBMS</PackageTags>
<RepositoryUrl>https://github.com/pine-vm/pine.git</RepositoryUrl>
Expand Down
88 changes: 33 additions & 55 deletions implement/pine/ElmTime/compile-elm-program/src/FirCompiler.elm
Original file line number Diff line number Diff line change
Expand Up @@ -901,63 +901,41 @@ The first element in the list is a set of declarations that do not depend on any
recursionDomainsFromDeclarationDependencies : List ( String, Set.Set String ) -> List (Set.Set String)
recursionDomainsFromDeclarationDependencies declarationDependencies =
let
integrateDecl ( declName, declDependencies ) recursionDomains =
let
-- Inserts the new domain into the list of domains at the position where the none of the following domains depend on it.
insertDomainRecursive :
Set.Set String
-> List (Set.Set String)
-> List (Set.Set String)
-> List (Set.Set String)
insertDomainRecursive domainToInsert skipped following =
case following of
[] ->
skipped ++ [ domainToInsert ]

next :: rest ->
let
allCurrentAndFollowing : Set.Set String
allCurrentAndFollowing =
List.foldl Set.union next rest

dependingOnAnyCurrentOrFollowing : Bool
dependingOnAnyCurrentOrFollowing =
not (Set.isEmpty (Set.intersect declDependencies allCurrentAndFollowing))

allDependenciesOfNext : Set.Set String
allDependenciesOfNext =
Set.foldl
(\nextDeclName aggregate ->
case Common.assocListGet nextDeclName declarationDependencies of
Nothing ->
aggregate

Just nextDeclDependencies ->
Set.union nextDeclDependencies aggregate
)
Set.empty
next

nextDependingOnNewDomain : Bool
nextDependingOnNewDomain =
Set.member declName allDependenciesOfNext
in
if dependingOnAnyCurrentOrFollowing then
if nextDependingOnNewDomain then
-- Merge the new domain into the current domain
List.concat
[ skipped, [ Set.union domainToInsert next ], rest ]

else
insertDomainRecursive domainToInsert (skipped ++ [ next ]) rest
depsGroups : List (Set.Set String)
depsGroups =
List.map
(\( declName, declDependencies ) -> Set.insert declName declDependencies)
declarationDependencies

depsGroupsUniqueOrdered : List (Set.Set String)
depsGroupsUniqueOrdered =
List.sortBy Set.size (Common.listUnique depsGroups)

deriveDomainsRecursive :
Set.Set String
-> List (Set.Set String)
-> List (Set.Set String)
-> List (Set.Set String)
deriveDomainsRecursive covered groups domains =
case groups of
[] ->
List.reverse domains

else
List.concat
[ skipped, [ domainToInsert ], following ]
in
insertDomainRecursive (Set.singleton declName) [] recursionDomains
nextGroup :: remainingGroups ->
let
domain : Set.Set String
domain =
Set.filter
(\name -> not (Set.member name covered))
nextGroup

coveredNext : Set.Set String
coveredNext =
Set.union nextGroup covered
in
deriveDomainsRecursive coveredNext remainingGroups (domain :: domains)
in
List.foldl integrateDecl [] declarationDependencies
deriveDomainsRecursive Set.empty depsGroupsUniqueOrdered []


parseFunctionParameters : Expression -> DeclBlockFunctionEntry
Expand Down
2 changes: 1 addition & 1 deletion implement/pine/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace ElmTime;

public class Program
{
public static string AppVersionId => "0.3.14";
public static string AppVersionId => "0.3.15";

private static int AdminInterfaceDefaultPort => 4000;

Expand Down
4 changes: 2 additions & 2 deletions implement/pine/pine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>pine</AssemblyName>
<AssemblyVersion>0.3.14</AssemblyVersion>
<FileVersion>0.3.14</FileVersion>
<AssemblyVersion>0.3.15</AssemblyVersion>
<FileVersion>0.3.15</FileVersion>
<Nullable>enable</Nullable>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
Expand Down

0 comments on commit fb76785

Please sign in to comment.