Fsharp: Can FSharp.Core for .NET Core be splet into a few NuGet packages like .NET Core is

Created on 7 Dec 2016  路  5Comments  路  Source: dotnet/fsharp

Maybe it is reasonable to split FSharp.Core into a few packages?

I use F# bindings for System.Collections.Immutable and I would perfectly throw away F# collections.
There is a task computation expression in an Orleankka (because of custom task scheduler) that will be much better for interoperability so asynchronous workflows can be thrown away too.

Hence what is the reason to have a single monolithic package instead of small compostable pieces?

Most helpful comment

My opinion: The multiple iterations of .NET Core library refactoring and fragmentation (old-portable, now-portable-4.5, new-portable-4.6, WinRT, netcore, netstandard 1.0/.../1.6, netstandard 2.0) have been like blowing up bomb after bomb in the middle of the .NET ecosystem. From the point of view of a tool-provider, these changes have been vastly difficult to cope with and have sooooo many corner cases. They make the basics of .NET so complex that it's near impossible to do anything except via yet another layer of tooling (project.json/dotnet/msbuild). And that layer keeps changing and changing, and supports F# imperfectly. Further this extra layer of tooling makes the C#, F# and .NET Communities even more dependent on magic tooling than ever before. Together these initiatives have inflicted huge costs on every provider of .NET tooling or components, for what sometimes feel like imperceptible gains.

So all that doesn't leave me wanting to follow the same direction for FSharp.Core. Also I suspect it's not technically feasible to do it without breaking binary compatibility and forking the F# library ecosystem.

All 5 comments

I'm feeling Trolled right now :-)

A monolithic FSharp.Core.dll has a number of advantages and disadvantages.

The main disadvantages are

  1. Working set wasted on unused types,
  2. Reduced portability due to functions that are not available everywhere.

The main advantages are

  1. Simpler deployment, easier construction of command lines.
  2. Better performance

    • Runtime Loading and Laying out 4 dll's takes a lot longer than one dll.

    • Compile time references of 4 dll's takes a lot longer than one dll.

  3. Improved inlining, doesn't need cross module inlinlining
  4. Compatibility
  5. Improved Working Set ... memory overhead of each loaded dll is a constant + the complexity of the types in the dll.

On CoreCLR with partitioned assemblies you don't pay at as much of this overhead as you would think because many of the BCL types are in System.PrivateCore.dll.

Furthermore when Ahead of Time Compilation becomes commonplace in dotnet then we will only included accessed types and methods in the finished binary. And so all of the gains from refactoring will be immediately available without the hard work of figuring out a factoring strategy that is generally usable.

Anyway I don't want to discourage a conversation merely put down a marker about how I think about this.

This is how fragmented the build on coreclr now is, without tooling I doubt we would get these references right

E.g.
This is from the Coreclr build of FSharp.Compiler.dll (61 dlls) it replaces 14 referenced dll's in the desktop build:
-r:c:\kevinransom\visualfsharp\Release\coreclr\bin\FSharp.Core.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\Microsoft.DiaSymReader\1.0.8\lib\netstandard1.1\Microsoft.DiaSymReader.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\Microsoft.DiaSymReader.PortablePdb\1.1.0\lib\netstandard1.1\Microsoft.DiaSymReader.PortablePdb.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\Microsoft.Win32.Primitives\4.0.1\ref\netstandard1.3\Microsoft.Win32.Primitives.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.AppContext\4.1.0\ref\netstandard1.6\System.AppContext.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Collections.Concurrent\4.0.12\ref\netstandard1.3\System.Collections.Concurrent.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Collections\4.0.11\ref\netstandard1.3\System.Collections.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Collections.Immutable\1.2.0\lib\netstandard1.0\System.Collections.Immutable.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Console\4.0.0\ref\netstandard1.3\System.Console.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Diagnostics.Debug\4.0.11\ref\netstandard1.3\System.Diagnostics.Debug.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Diagnostics.Process\4.1.0\ref\netstandard1.4\System.Diagnostics.Process.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Diagnostics.Tools\4.0.1\ref\netstandard1.0\System.Diagnostics.Tools.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Diagnostics.TraceSource\4.0.0\ref\netstandard1.3\System.Diagnostics.TraceSource.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Diagnostics.Tracing\4.1.0\ref\netstandard1.5\System.Diagnostics.Tracing.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Globalization.Calendars\4.0.1\ref\netstandard1.3\System.Globalization.Calendars.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Globalization\4.0.11\ref\netstandard1.3\System.Globalization.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.IO.Compression\4.1.0\ref\netstandard1.3\System.IO.Compression.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.IO.Compression.ZipFile\4.0.1\ref\netstandard1.3\System.IO.Compression.ZipFile.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.IO\4.1.0\ref\netstandard1.5\System.IO.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.IO.FileSystem\4.0.1\ref\netstandard1.3\System.IO.FileSystem.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.IO.FileSystem.Primitives\4.0.1\ref\netstandard1.3\System.IO.FileSystem.Primitives.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Linq\4.1.0\ref\netstandard1.6\System.Linq.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Linq.Expressions\4.1.0\ref\netstandard1.6\System.Linq.Expressions.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Linq.Queryable\4.0.1\ref\netstandard1.0\System.Linq.Queryable.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Net.Http\4.1.0\ref\netstandard1.3\System.Net.Http.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Net.Primitives\4.0.11\ref\netstandard1.3\System.Net.Primitives.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Net.Requests\4.0.11\ref\netstandard1.3\System.Net.Requests.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Net.Sockets\4.1.0\ref\netstandard1.3\System.Net.Sockets.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Net.WebHeaderCollection\4.0.1\ref\netstandard1.3\System.Net.WebHeaderCollection.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.ObjectModel\4.0.12\ref\netstandard1.3\System.ObjectModel.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Reflection\4.1.0\ref\netstandard1.5\System.Reflection.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Reflection.Emit\4.0.1\ref\netstandard1.1\System.Reflection.Emit.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Reflection.Emit.ILGeneration\4.0.1\ref\netstandard1.0\System.Reflection.Emit.ILGeneration.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Reflection.Extensions\4.0.1\ref\netstandard1.0\System.Reflection.Extensions.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Reflection.Metadata\1.4.1-beta-24227-04\lib\netstandard1.1\System.Reflection.Metadata.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Reflection.Primitives\4.0.1\ref\netstandard1.0\System.Reflection.Primitives.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Reflection.TypeExtensions\4.1.0\ref\netstandard1.5\System.Reflection.TypeExtensions.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Resources.ResourceManager\4.0.1\ref\netstandard1.0\System.Resources.ResourceManager.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Runtime\4.1.0\ref\netstandard1.5\System.Runtime.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Runtime.Extensions\4.1.0\ref\netstandard1.5\System.Runtime.Extensions.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Runtime.Handles\4.0.1\ref\netstandard1.3\System.Runtime.Handles.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Runtime.InteropServices\4.1.0\ref\netstandard1.5\System.Runtime.InteropServices.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Runtime.InteropServices.RuntimeInformation\4.0.0\ref\netstandard1.1\System.Runtime.InteropServices.RuntimeInformation.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Runtime.Loader\4.0.0\ref\netstandard1.5\System.Runtime.Loader.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Runtime.Numerics\4.0.1\ref\netstandard1.1\System.Runtime.Numerics.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Security.Cryptography.Algorithms\4.2.0\ref\netstandard1.6\System.Security.Cryptography.Algorithms.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Security.Cryptography.Encoding\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Encoding.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Security.Cryptography.Primitives\4.0.0\ref\netstandard1.3\System.Security.Cryptography.Primitives.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Security.Cryptography.X509Certificates\4.1.0\ref\netstandard1.4\System.Security.Cryptography.X509Certificates.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Text.Encoding\4.0.11\ref\netstandard1.3\System.Text.Encoding.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Text.Encoding.Extensions\4.0.11\ref\netstandard1.3\System.Text.Encoding.Extensions.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Text.RegularExpressions\4.1.0\ref\netstandard1.6\System.Text.RegularExpressions.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Threading\4.0.11\ref\netstandard1.3\System.Threading.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Threading.Tasks\4.0.11\ref\netstandard1.3\System.Threading.Tasks.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Threading.Tasks.Parallel\4.0.1\ref\netstandard1.1\System.Threading.Tasks.Parallel.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Threading.Thread\4.0.0\ref\netstandard1.3\System.Threading.Thread.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Threading.ThreadPool\4.0.10\ref\netstandard1.3\System.Threading.ThreadPool.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Threading.Timer\4.0.1\ref\netstandard1.2\System.Threading.Timer.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.ValueTuple\4.0.0-rc3-24212-01\lib\netstandard1.1\System.ValueTuple.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Xml.ReaderWriter\4.0.11\ref\netstandard1.3\System.Xml.ReaderWriter.dll -r:c:\kevinransom\visualfsharp\src\fsharp\FSharp.Compiler\..\..\..\packages\System.Xml.XDocument\4.0.11\ref\netstandard1.3\System.Xml.XDocument.dll

I'd prefer it stay together, especially for the case of me migrating the tryfsharp tutorials.

My opinion: The multiple iterations of .NET Core library refactoring and fragmentation (old-portable, now-portable-4.5, new-portable-4.6, WinRT, netcore, netstandard 1.0/.../1.6, netstandard 2.0) have been like blowing up bomb after bomb in the middle of the .NET ecosystem. From the point of view of a tool-provider, these changes have been vastly difficult to cope with and have sooooo many corner cases. They make the basics of .NET so complex that it's near impossible to do anything except via yet another layer of tooling (project.json/dotnet/msbuild). And that layer keeps changing and changing, and supports F# imperfectly. Further this extra layer of tooling makes the C#, F# and .NET Communities even more dependent on magic tooling than ever before. Together these initiatives have inflicted huge costs on every provider of .NET tooling or components, for what sometimes feel like imperceptible gains.

So all that doesn't leave me wanting to follow the same direction for FSharp.Core. Also I suspect it's not technically feasible to do it without breaking binary compatibility and forking the F# library ecosystem.

Closing for now.

A side effect of having or creating a library that consists of multiple packages is that improves its maintainability and portability. F# Core may get more contributions if it was more componentized and it would be easier to make it more portable as mentioned in #1217. I remember trying to figure out how equality in F# Core is implemented for different types and it was no fun jumping around in a 3000 line file. I find maintainability and portability more important than performance concerns (assembly loading and memory footprint), which would also go away with Ahead of Time compilation. Whether all the pain of refactoring F# Core is worth it at this time is another question.

Was this page helpful?
0 / 5 - 0 ratings