I'll translate my ray tracer benchmark into F# and post the results ASAP.
Hey Jon,
I apologize for being a little off topic and cheeky here but I was wondering how that Ray tracer benchmark was coming?
Are you so jazzed about Jocaml that you have forsaken us over here in the F# world?
I would also like to ask you about your thoughts about how the ocamlP3/jocaml multi-process implementations compare to F# (in terms of performance, ease of use)?
Is it true that jocaml relies on the Unix fork process command and thus cannot be ported to Windows?
Parnell
To cut to the chase, the Java and .NET approach to concurrency (using a single concurrent GC) works on Unix and Windows and offers the best performance for fine-grained concurrent applications but slows all allocations down by ~5x, does not scale to massive concurrency (millions of threads) and does not translate to distributed concurrency.
The OCaml/JoCaml approach to concurrency (forking processes using copy-on-write to give independent processes with their own GCs) works on Unix and offers the best performance for coarse-grained concurrent applications and is easily distributed but does not work on Windows, slows down fine-grained concurrent applications and also does not scale to massive concurrency.
The Erlang approach to concurrency (independent mini-GCs with unidirectional heaps) scales to massively concurrent applications but imposes more intrusive rules on the programmer (e.g. no cycles in the heap).
So there is no clear winner.
Note that functional programming languages compiling idiomatic functional programs to .NET will give pathologically bad performance due to their heavy allocation of short-lived objects.
I predict that the first F# translations on the Great Computer Language Shootout will be minimal translations of the OCaml implementations. As a consequence of the above, this will show F# in an unfairly-poor light because the programs will need reoptimizing (by avoiding rapid allocation at all costs). Another problem is that the shootout tasks are sufficiently ill-specified that most of the programs can be arbitrarily optimized away. Consequently, the maintainers are forced to subjectively reject submissions and, I suspect, they will reject most of the F#-specific optimizations.
Although it is interesting for a few people to compare the performance of OCaml and F#, the vast majority of people interested in F# are currently using C++ and C# rather than OCaml (statistics from the F# Journal survey). At least for the C# programmers, relative performance will be of little interest!
Finally, I should say that the factor of 5 that I referred to above is taken from the Sudoku Solver application articles in the OCaml and F# Journals. The implementations of the idiomatic purely functional solver algorithm are identical in both languages and the OCaml is 5x faster. The F# could be optimized by using a more sophisticated representation of a heap with more preallocated memory and larger chunks but this was not necessary in practice because all Sudoku puzzles can be solved in <0.01s, so the GUI remains responsive.
HTH.
I've been using F#/Mono on OS X off and on. My understanding of the poor performance there revolves around three issues.
- Mono Garbage Collection. The mono runtime still uses Boehm's conservative garbage collector. While that collector is well written, understood by industry, etc. it is not a compacting collector, which means it does not give you the "free" locality of reference boost that Microsoft's CLR does. I suppose the amount of garbage created by each benchmark would influence the delta between Mono & CLR; does this stand up? I am not sure what the mono team's plans on replacing the GC are.
- Less impressive JIT compiler. Besides diving into very deep binary debugging sessions, I'm not sure how to evaluate the quality of the code produced by the mono JIT compiler, but this presentation suggests that it does very little optmization. This might make all the difference.
- No Generics(?). Since ahead-of-time compilation with .NET 2.0 features is not yet supported on Mono, perhaps the F# compiler is working at a disadvantage here? (Question mark because this comment may be out of date. Things change so fast!)
I'd be curious to see your speculation on which of the above (or none of the above!) factors is affecting the difference between the CLR and Mono versions.
Thanks for sharing the results of this study, while I agree that these kind of results should generally be taken if a pinch of salt, I think these kind of benmarks do serve a purpose, in that taking carefully taking a benchmark and refining your program then retaking the benchmark is pretty much the only way to address preformance issues.
It is interesting that pidigits test does not preform very well, I know the F# team were looking at improving this, it has already been discussed on this thread here:
[link:cs.hubfs.net]
Hi guys
Thanks for the analysis - and good caveats.
I took a look at pidigits last night and found numerous improvements that can be made to the BigInt implementation - neow about 40% faster. We'll get those fixes into the next release.
Kind regards
don
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hi,
In examining the viability of converting an existing ocaml codebase to F# I recently ran some performance benchmarks and was pleasantly surprised by the results (reproduced below), The code used to benchmark is not my own - it comes from the ocaml submissions to the Computer Language Benchmarks Game. I think everybody realises how little you can read into benchmarks. They are afterall particular implementations of particular algorithms (often not written in the dominant idiom of the language), compiled/interpreted with a particular implementation, run on particular hardware etc. So with that said, I hope nobody takes this post as an attempt to 'prove' something definite about the performance of F# code relative to other languages. I've posted this purely because I thought one or two people might be interested.
Some notes on the methodology (in no particular order):
1. Programs were taken from the language shootout ocaml submissions where the ocaml source either needed no changes to compile or the changes were extremely trivial changes in syntax (i.e removal of ocaml named arguments, addition of spaces between brackets).
2. All tests were run three times and the mean taken as the result. The time was measured using the *nix 'time' utility. On windows the tests were run from a cygwin shell in order to have access to this utility.
3. Ocaml programs were built with the native code compiler (ocamlopt) using the flags suggested by the shootout.
4. F# programs were built using VS 2005 release mode on Windows XP. Mono version was 1.2.2.1 with flag --optimize=all. The ahead of time compiler was not used because fsc produces .NET 2.0 assemblies for which aot doesn't work (apparently, I'm no Mono expert).
5. gcc programs were built with the flags suggested by the shootout except with march changed to athlon-xp and -mfpmath=sse -msse2 added in 2 cases where they are omitted by the shootout but produce a performance increase on my machine.
6. Mono F# and gcc were both built and run on Linux (Gentoo). I realise it would have been better to run all benchmarks under one operating system but things didn't work out that way and as stated above - this exercise was always intended to be taken with a pinch of salt.
Some notes on the results:
1. F# performance with the Microsoft runtime is generally very good. In two cases actually beating c code compiled specifically for the testing hardware (see n-body and spectral norm). I'm guessing that this is to do with some very clever floating point arithmetic optimisations in the .NET compiler.
2. F# does poorly on two benchmarks (pidigits and startup). I think its safe to ignore the startup benchmark since most programs actually do some work. I've no idea why F# does badly on pidigits, although one thing I did notice is that ocaml buffers output whereas F# seems to flush the output stream after every call to printf. C blows the competition out of the water on pidigits probably because of the use of gmp.
3. Mono F# is definitely the poorest performer on the benchmark, although most of the times are respectable. This may in part be due to my lack of knowledge about Mono. Personally, I expect Mono performance to increase with future releases.
Results:<table><tr><td></td><td>F# .NET</td><td>F# Mono (Linux)<td>ocaml(XP)<td>ocaml (Linux)<td>gcc (Linux)</tr><tr><td>Binary Trees (n = 16)</td><td>2.563</td><td>7.499</td><td>2.281</td><td>2.269</td><td>2.408</td></tr><tr><td>Fannkuch (n = 11)</td><td>6.188</td><td>9.337</td><td>6.610</td><td>6.303</td><td>4.130</td></tr><tr><td>Nsieve (n = 9)</td><td>0.906</td><td>1.805</td><td>0.844</td><td>0.712</td><td>0.539</td></tr><tr><td>N-body (n = 20000000)</td><td>7.328</td><td>36.896</td><td>36.969</td><td>23.939</td><td>7.398</td></tr><tr><td>Partialsums (n = 2500000)</td><td>1.610</td><td>2.395</td><td>2.422</td><td>1.648</td><td>1.314</td></tr><tr><td>Pidigits (n = 2500)</td><td>9.515</td><td>13.428</td><td>2.016</td><td>1.647</td><td>0.370</td></tr><tr><td>Recursive (n = 11)</td><td>3.172</td><td>3.515</td><td>4.797</td><td>4.664</td><td>1.541</td></tr><tr><td>Spectral-norm (n = 5500)</td><td>9.843</td><td>26.253</td><td>52.859</td><td>51.222</td><td>10.889</td></tr><tr><td>Startup</td><td>0.235</td><td>0.062</td><td>0.031</td><td>0.001</td><td>0.001</td></tr></table>Ben Jackson.