For someone who is looking from the outside, the many flavors of .net can be very confusing. This post tries to summarize the various .net implementations:
- .net framework: The version of .net that most people are familiar with. .net framework is the Windows-only framework that can be used for Windows client apps using frameworks such as WPF and WinForms. This is also the version supported by prior web frameworks such as webforms and older versions of asp.net. This version generally ships with windows and generally updated via windows update.
- .net core: The new hotness that just hit version 1.0 in June 2016. .net core is a cross-platform (Windows, Linux, OSX), MIT licensed open-source implementation of .net from Microsoft. .net core appears to be targeted more towards servers, web frameworks and cloud deployment. .net core is meant to be shipped as part of/alongside your app and is distributed via nuget. This release is also accompanied by “Asp.net core 1.0” which also runs on .net core and thus gains the ability to run cross-platform. Microsoft does not provide a GUI toolkit for client apps for .net core though third-party solutions may emerge. While .net core shares some underlying code such as GC and JIT compiler from .net framework, the API exposed by .net core is not 100% compatible with .net framework.
- Mono: Open-source implementation of .net framework that runs on many different platforms including Linux, OSX, BSD, Android and some game consoles such as Playstation 3. This is under the stewardship of Xamarin (earlier and independent company and now a subidiary of Microsoft). Mono was developed independently from Microsoft and has its own GC and JIT etc. So right now there are two different open-source .net implementations for Linux and OSX: Mono and .net core!
- .net native for Windows 10/UWP: The .net portion of UWP is based upon .net core. However, instead of running apps on top of the .net core CLR, all UWP apps submitted to the Windows store for Windows 10 are compiled ahead-of-time into native code using a proprietary Microsoft tool. This tooling is called “.net native” for UWP. This tooling has some limitations. For example, F# cannot be used with .net native though Microsoft is working on fixing that.
- Mono for iOS: An ahead-of-time compiled implementation of .net for iOS based upon Mono.
- Other misc targets:There are many more versions that are now irrelevant such as Silverlight, .net for Windows Phone 8 and .net micro.
The API surfaces exposed by various implementations are not 100% compatible with each other. This can be a big issue for library writers. Currently, this is “solved” by “portable class library” (PCL) where the developer defines the targets the library is supposed to be portable to and then the compiler will expose the intersection of API surfaces exposed by the targeted platforms. But what if there is a new platform X later on? PCL is tied to the targeted platforms and cannot be run on this hypothetical X even if X exposes all the APIs necessary for the compiled PCL.
Microsoft is trying to address the issue of library (and also programmer knowledge) portability by a new initiative called “.net standard library”. The idea is that there will be a versioned standard library definition. Each platform will advertise which version of the standard library it supports. The standard library will always be backwards compatible (eg: a platform supporting .net standard library 1.3 will also support 1.1). Portable libraries will compile against a particular version of the .net standard library and will then be portable to all current and future platforms that support that version of the library. Microsoft will also focus its own library development plans on this .net standard instead of tying them to a partiular .net implementation.
To summarize, it is amazing to see that .net is now available on almost every platform. Furthermore, many of the implementations of .net are open-soure and developed in the open. On the other hand, the API fragmentation across platforms was also an issue and hopefully .net standard library will make it easy to write cross-platform libraries in the future.
I have been getting more into F# and the language does seem very elegant. It is not a small language with lots of ideas and concepts from both FP and OO worlds blended together, but somehow the blend chosen makes a lot of sense to me. I don’t yet have experience of writing large programs in F#, mostly short snippets. I feel that I have grasped most of the basic concepts though some advanced concepts are still a bit out of scope for me. And I am not experienced enough to be able to see which language features make the most sense in various scenarios.
As it happens, an interesting F# book, called F# deep dives came out recently. This is a collection of case-studies of using F# in various domains. Each chapter is written by a different person, and they describe a particular problem in their domain and how they solved it using F#. This is not a hand-wavey software architecture book though. Each chapter comes with code and some discussion of the design decisions. I was interested in the book from the perspective of learning about how various features of F# can be utilized in real-world scenarios.
I like the book overall. I liked some chapters such as the chapters on MVC pattern for GUI development in F#, the one on type providers and also the chapter about game development in F#. However, the quality and style of of writing is very uneven as can be expected from a book where each chapter was contributed by a different author. I feel that everyone will have their own favorite chapters and also chapters that bored them, depending on what they want to use F# for. One annoying thing about the book is that there is no syntax highlighting at all. It makes the code harder to read. The book also seems to be very text heavy, with very few visual aids or diagrams presented.
Overall, I had high expectations for the book and it did not meet them. It is an interesting book for programmers who know at least some F# and has some good content but it is not a must-have.
Some things I want to experiment with as a fun exercise:
F# : F# is an awesome language that I started experimenting with a few months back. While I know the basic syntax of many parts of the language now, I am nowhere near proficient. Even in my brief time with the language, I am enjoying it a lot. It is more productive than even Python and light years ahead of C++. Looking forward to playing with some of the interesting features such as async workflows and type providers. Two books that I have on my radar are “F# deep dives” and “Purely functional data-structures” by Okasaki.
C# and .net ecosystem: Playing with F# actually has made me interested in playing with more .net technologies. From the productivity standpoint, C# looks a lot nicer than Java or C++ and does have some interesting technologies such as async construct and LINQ. On the performance side, CLR looks like a good JIT and a lot of innovation and pragmatic decisions seem to have been taken in the .net ecosystem. For example, inclusion of value types, SIMD types introduced recently with RyuJIT and libraries such as TPL should make it possible to write reasonably high-performance code despite CLR being a managed runtime. Recent open-sourcing of the .net core is also an interesting move.
ZeroMQ: I don’t have much experience with message-queue based systems and ZeroMQ looks like a good place to start. Have heard a lot of good things about it.
C++11: I have read up on many of the features in C++11, and have a basic understanding, but have not used them in non-trivial ways so I am not confident about them yet. Overall I am not at all liking where C++ is going. However, as a professional programmer who works a lot with C++ I feel I should keep myself updated because I expect to see more C++11 going forward.
OpenCL 2.0: I have read the specs and am familiar with many of the features theoretically but want to spend some time with features such as device-side enqueue and SVM to see the types of algorithms that are now possible on modern hardware.
Direct3d 11 and 12: Well quite self-evident 🙂 Going with the .net theme might try out SharpDX perhaps instead of going the native route.
Recently, there was some discussion about a set of microbenchmarks reported in a study called Clash of the Lambdas which compared a simple stream/sequence benchmark using Java 8 Streams, Scala, C# LINQ and F#. I am learning F# and as a learning exercise I decided to re-implement one of the benchmarks (Sum of Squares Even) myself in F# without referring to the code provided by the authors.
The source of my implementation can be found on Bitbucket and binaries are also provided. My interest was to test/compare various F# implementations and not cross-language comparison. I implemented it in four different ways:
- Imperative sequential for-loop
- Imperative parallel version using Parallel.For from Task Parallel Library
- Functional sequential version using F# sequences
- Functional parallel version using F# PSeq from FSharp.ParallelSeq
- UPDATE: I added a functional version using the Nessos Streams package as suggested by Nick Palladinos on twitter
I compiled using VS 2013 Express and F#3.1 with “Release” settings, Any CPU (32-bit not preferred) and ran it on my machine on 3 different CLR implementations: MS CLR from .net SDK 4.5.2 running on Windows 8.1, MS CLR RyuJIT CTP4 and finally on OpenSUSE 13.1 using Mono 3.4 (sgen GC, no LLVM).
The results are as follows:
|MS RyuJIT CTP4
Some observations for this microbenchmark:
- Imperative version is far faster than the functional version, but the functional version was shorter and clearer to me. I wonder if there is some opportunity for compiler optimizations in the F# compiler for the functional version, such as inlining sequence operations or fusing a pipeline of operations where possible.
- MS RyuJIT CTP4, which is the beta version of the next-gen MS CLR JIT, is performing similar to the current MS CLR. This is good to see
- Mono is much slower than the MS CLR. Also, it absolutely hates F# parallel sequences for some reason. I guess I will have to try and install Mono with LLVM enabled and then check the performance again.
- Streams package from Nessos looks to be faster than F# sequences in this microbenchmark. It is currently sequential only but performs much faster than even PSeq.
These observations only apply to this microbenchmark, and probably should not be considered as general results. Overall, it was a fun learning experience, especially as a newcomer to both F# and the .net ecosystem. F# looks like a really elegant and powerful language and is a joy to write. There is still a LOT more to learn about both. For example, I am not quite clear what the best way to distribute .net projects as open-source. Should I distribute VS solution files? I am more used to distributing build files for CMake, Make, scons, ant etc. and looking more into FAKE. NuGet is also nice-ish though appears to be useful but not very powerful (eg: can’t remove packages) and merits further investigation.
Getting F# running on Linux took a lot more effort than I anticipated. I am documenting the process here in the hope it may benefit someone (maybe myself) in the future. For reference, I am using OpenSuse 13.1.
- F# is not compatible with all versions of Mono. For example, my distro repos have Mono 3.0.6 which appears to have some issues with F#. Instead, I found some people make new Mono packages available for various distros using Opensuse Build Service (OBS). For example, check out tpokorra repos for various distros such as OpenSUSE, CentOS, Debian etc. I installed “mono-opt” and related packages. It installed mono 3.4 into /opt/mono directory.
- If you install mono into /opt/mono, then ensure that you do append “/opt/mono/lib” into the LD_LIBRARY_PATH environment variable and /opt/mono/bin to the PATH variable. I did this in my .bashrc.
- By default, /opt/mono/bin/mono turned out to be a symlink to /opt/mono/bin/mono-sgen. Now it appears that Mono has two versions: one using sgen GC and one using Boehm GC. I have had trouble with compilng F# using mono-sgen so I removed /opt/mono/bin/mono and then created it as a symlink to /opt/mono/bin/mono-boehm.
- Now open up a new shell. In this shell, set up a few environment variables temporarily required for building F#. First, “export PKG_CONFIG_PATH=/opt/mono/lib/pkgconfig”. Next, we need to setup some GC parameters for Mono. It turns out compiling F# requires a lot of memory and Mono craps out with default GC parameters. I have a lot of memory in my laptop, so I set the Mono GC to use upto 2GB as follows: “export MONO_GC_PARAMS=max-heap-params=2G”. These two settings likely won’t be required after you have compiled and installed F#.
- Now you can follow the instructions given on the F# webpage.
Specifically I did
- git clone https://github.com/fsharp/fsharp
- cd fsharp
- ./autogen –prefix /opt/mono #Keep things consistent with rest of mono install
- make #Takes a lot of time
- make install