<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1779668156488517434</id><updated>2012-01-30T14:38:49.037-08:00</updated><category term='arm'/><category term='bitwise'/><category term='tools'/><category term='martin odersky'/><category term='local optimization'/><category term='tuples'/><category term='books'/><category term='bug'/><category term='bugs'/><category term='free'/><category term='f# for numerics'/><category term='f# for visualization'/><category term='boost'/><category term='simon marlow'/><category term='representation'/><category term='structural'/><category term='native code'/><category term='array'/><category term='generational garbage collection'/><category term='ocaml for scientists'/><category term='job'/><category term='shadow stack'/><category term='darcs'/><category term='printer'/><category term='sal mangano'/><category term='profits'/><category term='reliability'/><category term='video'/><category term='lexmark'/><category term='gc pause'/><category term='c++'/><category term='closures'/><category term='scheme'/><category term='visualization'/><category term='nacl'/><category term='mathematica'/><category term='java'/><category term='parallel arrays'/><category term='sadek drobi'/><category term='advantages'/><category term='type class'/><category term='leak'/><category term='numerical recipes'/><category term='graphics'/><category term='burton smith'/><category term='mailing list'/><category term='memory'/><category term='concurrency'/><category term='industry'/><category term='don stewart'/><category term='gpu'/><category term='io'/><category term='visual studio integration'/><category term='interview'/><category term='lecture'/><category term='polymorphic variants'/><category term='term rewriting'/><category term='compatibility'/><category term='computer programming'/><category term='sse'/><category term='asynchronous workflow'/><category term='optimization'/><category term='guido van rossum'/><category term='profit'/><category term='nvidia'/><category term='compiler'/><category term='copying collection'/><category term='lines of code'/><category term='block sorting'/><category term='thesis'/><category term='standard ml'/><category term='milestone'/><category term='disadvantages'/><category term='technical computing'/><category term='mark region'/><category term='allocation'/><category term='signal'/><category term='numerical methods'/><category term='latency'/><category term='householder reductions'/><category term='concurrent gc'/><category term='module system'/><category term='amorphous'/><category term='pa_monad'/><category term='google go'/><category term='plugin'/><category term='animation'/><category term='bloxors'/><category term='virtual machine'/><category term='polymorphism'/><category term='programming language'/><category term='london'/><category term='lexer'/><category term='jit'/><category term='paper'/><category term='share'/><category term='hitachi'/><category term='purely functional data structure'/><category term='f# for technical computing'/><category term='richard jones'/><category term='directx'/><category term='channel'/><category term='ray tracer'/><category term='numerics'/><category term='disruptor'/><category term='fortran'/><category term='imperative'/><category term='multicore'/><category term='ganesh sittampalam'/><category term='size'/><category term='real-time'/><category term='kde 4'/><category term='ml'/><category term='kde'/><category term='paul graham'/><category term='numeric tower'/><category term='consultant'/><category term='don syme'/><category term='netbook'/><category term='garbage collection'/><category term='source code'/><category term='template haskell'/><category term='popularity'/><category term='front end'/><category term='data compression'/><category term='academic'/><category term='beginner'/><category term='joe marshall'/><category term='laser'/><category term='western digital'/><category term='goroutine'/><category term='hewlett packard'/><category term='lwt'/><category term='hash table'/><category term='mark sweep'/><category term='clojure'/><category term='erlang'/><category term='bfg'/><category term='trading'/><category term='commercial'/><category term='discount'/><category term='erik meijer'/><category term='funding'/><category term='sml'/><category term='norman ramsey'/><category term='ocaml journal'/><category term='mlton'/><category term='herb sutter'/><category term='product'/><category term='code base'/><category term='trends'/><category term='rewrite'/><category term='c#'/><category term='verbosity'/><category term='running cost'/><category term='numerical'/><category term='mark compact'/><category term='rich hickey'/><category term='graphics card'/><category term='haskell'/><category term='sales'/><category term='sun'/><category term='macro'/><category term='.net'/><category term='performance'/><category term='eclipse'/><category term='review'/><category term='monte carlo'/><category term='cpu'/><category term='business'/><category term='scala'/><category term='ParallelTable'/><category term='heap'/><category term='conservative gc'/><category term='shared_ptr'/><category term='language'/><category term='variant type'/><category term='bubble sort'/><category term='regular expression'/><category term='game'/><category term='gainward'/><category term='MinCut'/><category term='qr decomposition'/><category term='parallel garbage collection'/><category term='rule'/><category term='products'/><category term='limitations'/><category term='stop-the-world'/><category term='joe pamer'/><category term='intel'/><category term='software'/><category term='o&apos;reilly'/><category term='color'/><category term='treadmill'/><category term='proper tail recursion'/><category term='managed code'/><category term='trend'/><category term='market'/><category term='clos'/><category term='quadcore'/><category term='boehm'/><category term='release'/><category term='corruption'/><category term='extensibility'/><category term='reference counting'/><category term='fft'/><category term='vista'/><category term='hp'/><category term='examples'/><category term='ide'/><category term='task parallelism'/><category term='articles'/><category term='book sales'/><category term='value'/><category term='median'/><category term='public'/><category term='asynchronous'/><category term='data parallel haskell'/><category term='apple'/><category term='monad'/><category term='gc'/><category term='heap sort'/><category term='ipad'/><category term='benchmark'/><category term='common language runtime'/><category term='f# meetup'/><category term='evolutionary'/><category term='accumulator generator'/><category term='easy'/><category term='stack overflow'/><category term='ghc'/><category term='concurrent'/><category term='f# for scientists'/><category term='f#'/><category term='virginity'/><category term='phd'/><category term='burrows wheeler'/><category term='fsharp'/><category term='python'/><category term='analysis'/><category term='f#.net'/><category term='comparison'/><category term='llvm'/><category term='debian'/><category term='parallel'/><category term='windows'/><category term='layout'/><category term='scientific computing'/><category term='bitvector'/><category term='industrial haskell group'/><category term='partial specialization'/><category term='linux'/><category term='tail calls'/><category term='parallel programming'/><category term='research'/><category term='quicksort'/><category term='color laser printer'/><category term='f#.net journal'/><category term='tutorial'/><category term='Texas Multicore Technologies'/><category term='maximization'/><category term='lisp'/><category term='simple'/><category term='reference type'/><category term='special offer'/><category term='jvm'/><category term='wavelet'/><category term='book'/><category term='reddit'/><category term='time-frequency analysis'/><category term='google chrome'/><category term='tco'/><category term='object oriented programming'/><category term='pattern matching'/><category term='diffraction'/><category term='hlvm'/><category term='jobs'/><category term='clr'/><category term='hard drive'/><category term='functional programming'/><category term='higher-order module'/><category term='fourier'/><category term='pattern'/><category term='microsoft'/><category term='ocaml'/><category term='concurrent garbage collector'/><category term='amd'/><category term='throughput'/><category term='symbolic'/><category term='parser'/><category term='mono'/><category term='g++'/><category term='message passing'/><category term='LMAX'/><category term='data'/><category term='loc'/><category term='pythagoras tree'/><category term='marvell'/><title type='text'>The Flying Frog Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default?start-index=101&amp;max-results=100'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>129</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-4249833226150677491</id><published>2012-01-15T02:58:00.000-08:00</published><updated>2012-01-18T14:17:06.152-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='trend'/><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='managed code'/><category scheme='http://www.blogger.com/atom/ns#' term='fortran'/><category scheme='http://www.blogger.com/atom/ns#' term='jobs'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='herb sutter'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><category scheme='http://www.blogger.com/atom/ns#' term='native code'/><category scheme='http://www.blogger.com/atom/ns#' term='sse'/><title type='text'>The "C++ renaissance"</title><content type='html'>According to Herb Sutter, C++ (and C and Fortran) are unmatched for performance per dollar and, therefore, he believes C++ will once again top the programming language charts as mobile devices make power consumption (which he equates with performance) a high priority again:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-rY4jtfaNKzA/TxVLhLWqkrI/AAAAAAAAAOQ/JHmh2M2-_Zk/s1600/C%252B%252BRenaissance.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="180" src="http://2.bp.blogspot.com/-rY4jtfaNKzA/TxVLhLWqkrI/AAAAAAAAAOQ/JHmh2M2-_Zk/s320/C%252B%252BRenaissance.GIF" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Herb said this in his recent lecture&amp;nbsp;&lt;a href="http://channel9.msdn.com/posts/C-and-Beyond-2011-Herb-Sutter-Why-C"&gt;Why C++?&lt;/a&gt;&amp;nbsp;and other Microsoft employees from the Visual C++ team have called this prophecy the&amp;nbsp;&lt;a href="http://channel9.msdn.com/Shows/Going+Deep/Craig-Symonds-and-Mohsen-Agsen-C-Renaissance"&gt;"C++ Renaissance"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Similar statements about the superior performance of C++ were commonplace over 15 years ago when Java was new and unproven but we now know they were almost entirely wrong. The world migrated from native to managed languages over 10 years ago and never looked back because their performance is more than adequate. Furthermore, the implementations of managed languages have improved substantially since then and even toy benchmarks now show them competing with or even beating native code. Furthermore, the difficulty of optimizing large code bases means that many real-world applications are substantially faster when written using modern tools. For example, we recently helped a client translate 10,000 lines of numerical C++ code into F# and were easily able to make it 10× faster than the original C++. This is typical because C++ is &lt;i&gt;much&lt;/i&gt; more difficult to optimize, particularly in the context of multicore parallelism, and developers in the real-world rarely have the time to do it if they are still using C++.&lt;br /&gt;&lt;br /&gt;So why would anyone be promoting C++ now when it has so many disadvantages. Several reasons, we believe. Firstly, C++0x was finally released as C++11 last year and Microsoft's Visual C++ team hope to ride a wave of hype following this. Secondly, Microsoft want to draw people back into C++ as a route to vendor lock-in. We have seen several big code bases written in "C++" using Microsoft's tools and none of them were remotely portable due to the extensive use of proprietary features. Ironically, Herb tries to play to portability in his preachings and even goes so far as to assert that C++ has the advantage of offering a single string type that is compatible with the operating systems. In addition, C++ is particularly bad for metaprogramming and, consequently, it is unusually difficult to translate code&amp;nbsp;mechanically&amp;nbsp;from C++ to other languages. Thirdly, what else do Microsoft's Visual C++ team have left to hype?&lt;br /&gt;&lt;br /&gt;Fortunately, this recent hype from Microsoft seems to have been largely ignored...&lt;br /&gt;&lt;br /&gt;Here is the current trend in the UK job market for C++ developers:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-gbj4-DZVxGQ/TxVLs76ePmI/AAAAAAAAAOY/6uU1VcygZ6w/s1600/C%252B%252BDevTrend.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="145" src="http://1.bp.blogspot.com/-gbj4-DZVxGQ/TxVLs76ePmI/AAAAAAAAAOY/6uU1VcygZ6w/s320/C%252B%252BDevTrend.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Is it about to change?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;EDIT&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Herb Sutter responded to some of my tweets about this. His responses are remarkable.&lt;br /&gt;&lt;br /&gt;Firstly, he states that "&lt;a href="https://twitter.com/#!/herbsutter/status/159335367638659072"&gt;no way should you need barriers to get sequential consistency&lt;/a&gt;". This is an amazing statement because all mainstream languages (Java, .NET, C++) and all dominant CPU architectures (ARM, Intel, AMD, PowerPC) require barriers to achieve sequential consistency. This property is ubiquitous because it is required for latency hiding to work effectively. The paper "&lt;a href="http://web.it.kth.se/~axel/papers/2011/ASPDAC-AbdulNaeem.pdf"&gt;Realization And Performance Comparison Of Sequential And Weak Memory Consistency Models In Network-on-Chip Based Multi-Core Systems&lt;/a&gt;" found that performance is around 40% worse if sequential consistency is imposed. ARM's Principal Software Engineer even went so far as to call sequentially consistent memory models a "&lt;a href="http://blogs.arm.com/software-enablement/431-memory-access-ordering-an-introduction/"&gt;nostalgic fantasy&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;In reality, ARM and PowerPC have weak memory models that allow many memory operations to be reordered and x86 has a stronger memory model that prohibits most reordering but still allows reads to be moved before independent writes and, consequently, is also not sequentially consistent. Note that Herb's dream of sequential consistency is at odds with the desire for more latency hiding that he expressed in his latest article.&lt;br /&gt;&lt;br /&gt;Then &lt;a href="https://twitter.com/#!/herbsutter/status/159337679887155200"&gt;he predicts that CPU vendors will adopt stronger memory models within 2 years&lt;/a&gt;. Perhaps Herb has inside knowledge of Microsoft leaning on ARM to adopt the x86 memory model to ease Microsoft's Windows 8 port. Only time will tell if Herb's prediction is accurate but two interesting observations can be made. Firstly, Apple have sold 10,000,000s of iPad 2's that are running the 500,000 apps on their AppStore without anyone having complained about bugs caused by the weak memory model of the multicore ARMs inside them. Secondly, Intel weakened the x86 memory model when they added SSE and, consequently, also added the LFENCE, SFENCE and MFENCE instructions. So Herb is predicting that Intel will do a U-turn and ARM will throw away one of their largest performance advantages.&lt;br /&gt;&lt;br /&gt;Finally, Herb asserts that "&lt;a href="https://twitter.com/#!/herbsutter/status/159698606578860033"&gt;x86 is the canonical example of a strong hardware memory model&lt;/a&gt;". Although many people can be seen asserting that the x86 has a strong memory model, many experts describe it as a weak memory model because it does reorder and does not provide sequential consistency. For example, computer science researchers in this field from the University of Cambridge describe x86 as having a weak memory model in their paper "&lt;a href="http://www.cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf"&gt;x86-TSO: A Rigorous and Usable Programmer’s Model for&amp;nbsp;x86 Multiprocessors&lt;/a&gt;". And computer science researchers from the University of Oxford&amp;nbsp;describe it as a&amp;nbsp;weak memory model in their paper "&lt;a href="http://www.cs.ox.ac.uk/people/jade.alglave/papers/aplas11.pdf"&gt;Soundness of Data Flow Analyses for&amp;nbsp;Weak Memory Models&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-4249833226150677491?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/4249833226150677491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=4249833226150677491' title='23 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4249833226150677491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4249833226150677491'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2012/01/c-renaissance.html' title='The &quot;C++ renaissance&quot;'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-rY4jtfaNKzA/TxVLhLWqkrI/AAAAAAAAAOQ/JHmh2M2-_Zk/s72-c/C%252B%252BRenaissance.GIF' height='72' width='72'/><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-1632747041143122141</id><published>2011-11-16T09:51:00.001-08:00</published><updated>2011-11-16T12:18:39.063-08:00</updated><title type='text'>What is your garbage collector collecting?</title><content type='html'>As a garbage collector runs it recycles unreachable values. A well known result in GC theory is that values tend to die in "clumps" rather than individually. This post visualizes these clumps.&lt;br /&gt;&lt;br /&gt;We instrumented a C++ program equipped with our own mark-region collector (using 64kB regions) that is equivalent to the following &lt;a href="http://www.ffconsultancy.com/products/fsharp_journal/?ffb"&gt;F#&lt;/a&gt; implementation of a list-based n-queens solver in order to gather information about the structures being collected:&lt;br /&gt;&lt;pre&gt;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#115;&amp;#097;&amp;#102;&amp;#101;&amp;#032;&amp;#120;&amp;#049;&amp;#032;&amp;#121;&amp;#049;&amp;#032;&amp;#120;&amp;#050;&amp;#032;&amp;#121;&amp;#050;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#120;&amp;#049;&amp;#032;&amp;#060;&amp;#062;&amp;#032;&amp;#120;&amp;#050;&amp;#032;&amp;#038;&amp;#038;&amp;#032;&amp;#121;&amp;#049;&amp;#032;&amp;#060;&amp;#062;&amp;#032;&amp;#121;&amp;#050;&amp;#032;&amp;#038;&amp;#038;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#120;&amp;#050;&amp;#032;&amp;#045;&amp;#032;&amp;#120;&amp;#049;&amp;#032;&amp;#060;&amp;#062;&amp;#032;&amp;#121;&amp;#050;&amp;#032;&amp;#045;&amp;#032;&amp;#121;&amp;#049;&amp;#032;&amp;#038;&amp;#038;&amp;#032;&amp;#120;&amp;#049;&amp;#032;&amp;#045;&amp;#032;&amp;#121;&amp;#050;&amp;#032;&amp;#060;&amp;#062;&amp;#032;&amp;#120;&amp;#050;&amp;#032;&amp;#045;&amp;#032;&amp;#121;&amp;#049;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#112;&amp;#115;&amp;#032;&amp;#110;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#091;&amp;#032;&amp;#102;&amp;#111;&amp;#114;&amp;#032;&amp;#105;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#049;&amp;#032;&amp;#046;&amp;#046;&amp;#032;&amp;#110;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#111;&amp;#114;&amp;#032;&amp;#106;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#049;&amp;#032;&amp;#046;&amp;#046;&amp;#032;&amp;#110;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#121;&amp;#105;&amp;#101;&amp;#108;&amp;#100;&amp;#032;&amp;#105;&amp;#044;&amp;#032;&amp;#106;&amp;#032;&amp;#093;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#114;&amp;#101;&amp;#099;&amp;#032;&amp;#102;&amp;#105;&amp;#108;&amp;#116;&amp;#101;&amp;#114;&amp;#032;&amp;#120;&amp;#048;&amp;#032;&amp;#121;&amp;#048;&amp;#032;&amp;#061;&amp;#032;&amp;#102;&amp;#117;&amp;#110;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#124;&amp;#032;&amp;#091;&amp;#093;&amp;#032;&amp;#045;&amp;#062;&amp;#032;&amp;#091;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#124;&amp;#032;&amp;#040;&amp;#120;&amp;#049;&amp;#044;&amp;#032;&amp;#121;&amp;#049;&amp;#032;&amp;#097;&amp;#115;&amp;#032;&amp;#113;&amp;#041;&amp;#058;&amp;#058;&amp;#120;&amp;#121;&amp;#115;&amp;#032;&amp;#097;&amp;#115;&amp;#032;&amp;#108;&amp;#105;&amp;#115;&amp;#116;&amp;#032;&amp;#045;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#120;&amp;#121;&amp;#115;&amp;#039;&amp;#032;&amp;#061;&amp;#032;&amp;#102;&amp;#105;&amp;#108;&amp;#116;&amp;#101;&amp;#114;&amp;#032;&amp;#120;&amp;#048;&amp;#032;&amp;#121;&amp;#048;&amp;#032;&amp;#120;&amp;#121;&amp;#115;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#115;&amp;#097;&amp;#102;&amp;#101;&amp;#032;&amp;#120;&amp;#048;&amp;#032;&amp;#121;&amp;#048;&amp;#032;&amp;#120;&amp;#049;&amp;#032;&amp;#121;&amp;#049;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#079;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#046;&amp;#082;&amp;#101;&amp;#102;&amp;#101;&amp;#114;&amp;#101;&amp;#110;&amp;#099;&amp;#101;&amp;#069;&amp;#113;&amp;#117;&amp;#097;&amp;#108;&amp;#115;&amp;#040;&amp;#120;&amp;#121;&amp;#115;&amp;#039;&amp;#044;&amp;#032;&amp;#120;&amp;#121;&amp;#115;&amp;#041;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#108;&amp;#105;&amp;#115;&amp;#116;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#113;&amp;#058;&amp;#058;&amp;#120;&amp;#121;&amp;#115;&amp;#039;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#120;&amp;#121;&amp;#115;&amp;#039;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#114;&amp;#101;&amp;#099;&amp;#032;&amp;#115;&amp;#101;&amp;#097;&amp;#114;&amp;#099;&amp;#104;&amp;#032;&amp;#110;&amp;#032;&amp;#110;&amp;#113;&amp;#115;&amp;#032;&amp;#113;&amp;#115;&amp;#032;&amp;#112;&amp;#115;&amp;#032;&amp;#097;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#109;&amp;#097;&amp;#116;&amp;#099;&amp;#104;&amp;#032;&amp;#112;&amp;#115;&amp;#032;&amp;#119;&amp;#105;&amp;#116;&amp;#104;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#124;&amp;#032;&amp;#091;&amp;#093;&amp;#032;&amp;#045;&amp;#062;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#110;&amp;#113;&amp;#115;&amp;#061;&amp;#110;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#097;&amp;#043;&amp;#049;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#097;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#124;&amp;#032;&amp;#040;&amp;#120;&amp;#044;&amp;#032;&amp;#121;&amp;#032;&amp;#097;&amp;#115;&amp;#032;&amp;#113;&amp;#041;&amp;#058;&amp;#058;&amp;#112;&amp;#115;&amp;#032;&amp;#045;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#101;&amp;#097;&amp;#114;&amp;#099;&amp;#104;&amp;#032;&amp;#110;&amp;#032;&amp;#110;&amp;#113;&amp;#115;&amp;#032;&amp;#113;&amp;#115;&amp;#032;&amp;#112;&amp;#115;&amp;#032;&amp;#097;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#124;&amp;#062;&amp;#032;&amp;#115;&amp;#101;&amp;#097;&amp;#114;&amp;#099;&amp;#104;&amp;#032;&amp;#110;&amp;#032;&amp;#040;&amp;#110;&amp;#113;&amp;#115;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#113;&amp;#058;&amp;#058;&amp;#113;&amp;#115;&amp;#041;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#108;&amp;#116;&amp;#101;&amp;#114;&amp;#032;&amp;#120;&amp;#032;&amp;#121;&amp;#032;&amp;#112;&amp;#115;&amp;#041;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#115;&amp;#111;&amp;#108;&amp;#118;&amp;#101;&amp;#032;&amp;#110;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#115;&amp;#101;&amp;#097;&amp;#114;&amp;#099;&amp;#104;&amp;#032;&amp;#110;&amp;#032;&amp;#048;&amp;#032;&amp;#091;&amp;#093;&amp;#032;&amp;#040;&amp;#112;&amp;#115;&amp;#032;&amp;#110;&amp;#041;&amp;#032;&amp;#048;&lt;/pre&gt;&lt;br /&gt;Stopping this program on its 1,000th GC cycle when it is solving the 11-queens problem, extracting references between allocated but unmarked cons cells, filtering out connected components with 3 or more vertices and visualizing the result using Mathematica's &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;GraphPlot&lt;/span&gt; function gives the following:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-cJaxQNDNfmk/TsP5vDczYdI/AAAAAAAAANo/vpRo7qcTxTM/s1600/GarbageCollectionConnectivity.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-cJaxQNDNfmk/TsP5vDczYdI/AAAAAAAAANo/vpRo7qcTxTM/s1600/GarbageCollectionConnectivity.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;In this case, we find that just 6% of the cons cells die alone (i.e. singleton lists) and 84% die in a clump of two cons cells, 6.5% die in a clump of 3 cons cells and 3.4% die in clumps containing four or more cons cells. Only a handful of clumps had interesting structures.&lt;br /&gt;&lt;br /&gt;Although these results suggest that it might be easy to obtain a speedup by adding a special case to the list type for lists containing two elements we have found that this is not the case because the required changes also add expensive operations elsewhere, e.g. destructuring the special two-element list now incurs an allocation. Therefore, the next best solution would be to optimize the garbage collector for this case but it would be prudent to analyze the clusters collected during the running of other programs first. Analyzing the garbage generated by a program using red-black trees would be interesting...&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-1632747041143122141?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/1632747041143122141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=1632747041143122141' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1632747041143122141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1632747041143122141'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/11/what-is-your-garbage-collector.html' title='What is your garbage collector collecting?'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-cJaxQNDNfmk/TsP5vDczYdI/AAAAAAAAANo/vpRo7qcTxTM/s72-c/GarbageCollectionConnectivity.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-3780475769835433487</id><published>2011-11-14T08:16:00.000-08:00</published><updated>2011-11-14T09:54:05.288-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='trading'/><category scheme='http://www.blogger.com/atom/ns#' term='disruptor'/><category scheme='http://www.blogger.com/atom/ns#' term='treadmill'/><category scheme='http://www.blogger.com/atom/ns#' term='LMAX'/><category scheme='http://www.blogger.com/atom/ns#' term='latency'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='real-time'/><title type='text'>The LMAX disruptor and Baker's Treadmill</title><content type='html'>&lt;p&gt;A new retail financial trading platform called &lt;a href="http://www.lmaxtrader.co.uk/"&gt;LMAX&lt;/a&gt; recently published &lt;a href="http://code.google.com/p/disruptor/"&gt;their work&lt;/a&gt; on new software technology for low-latency servers that they call the "disruptor":&lt;/p&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/-8Tt6YNbzDu0/TsFHRyExNsI/AAAAAAAAANU/GYQAlYKQjLE/s1600/disruptor.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 311px;" src="http://4.bp.blogspot.com/-8Tt6YNbzDu0/TsFHRyExNsI/AAAAAAAAANU/GYQAlYKQjLE/s400/disruptor.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5674895376288659138" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;We have noticed a striking similiarity between their disruptor and an old garbage collection algorithm from 1992 called &lt;a href="http://www.memorymanagement.org/glossary/t.html#treadmill"&gt;Baker's Treadmill&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/-q0XKFqwOlzo/TsFHjxmh04I/AAAAAAAAANg/rxTqFU0XTec/s1600/treadmill.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 378px; height: 394px;" src="http://4.bp.blogspot.com/-q0XKFqwOlzo/TsFHjxmh04I/AAAAAAAAANg/rxTqFU0XTec/s400/treadmill.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5674895685399466882" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The LMAX disruptor and &lt;a href="http://martinfowler.com/articles/lmax.html"&gt;the story behind it&lt;/a&gt; are very interesting in their own right and well worth reading up on. In their system, binary messages come from the "receiver" and are distributed to the "journaller", "replicator" and "unmarshaller" in parallel and the "unmarshaller" then passes on the deserialized messages to the "consumer". The core of their idea is to accomplish all of this message passing using a single shared data structure, the disruptor, rather than using several separate concurrent queues.&lt;/p&gt;&lt;p&gt;Baker's Treadmill is a low-latency garbage collection algorithm. Allocated blocks in the heap are linked together to form a cyclic doubly-linked list that is divided into four segments using four iterators that chase each other around the ring as heap blocks are allocated, traced and freed. In addition to making all of the necessary operations incremental, this algorithm is interesting because it migrates heap blocks between its "to", "from", "new" and "free" spaces without physically copying them as so-called &lt;a href="http://www.memorymanagement.org/glossary/c.html#copying.garbage.collection"&gt;copying GC algorithms&lt;/a&gt; do (e.g. &lt;a href="http://www.memorymanagement.org/glossary/t.html#two-space.collector"&gt;Cheney semi-space&lt;/a&gt; or the nursery in a generational GC). Although this kind of logical migration is very valuable it is surprisingly uncommon in GC research literature. The &lt;a href="http://doc.cat-v.org/inferno/concurrent_gc/"&gt;VCGC algorithm&lt;/a&gt; is another example of a GC algorithm that logically migrates heap blocks between "young", "old" and "dead" spaces or "epochs" as the authors call them.&lt;/p&gt;&lt;p&gt;Beyond the striking resemblance of the disruptor to the Treadmill, there are some important differences:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The disruptor is a thread-safe concurrent data structure whereas the Treadmill was designed for single-threaded use.&lt;/li&gt;&lt;li&gt;The disruptor was designed to flow data from producers to consumers whereas the Treadmill also requires the ability to move an element from one segment of the ring to another.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Despite these differences, we think it is interesting to observe the similarities between these two different data structures and to note that they were both designed for low latency. Given that Baker's Treadmill is now quite dated in terms of low latency GC algorithms, perhaps future work on low-latency data structures can borrow from more recent GC theory?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-3780475769835433487?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/3780475769835433487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=3780475769835433487' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3780475769835433487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3780475769835433487'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/11/lmax-disruptor-and-bakers-treadmill.html' title='The LMAX disruptor and Baker&apos;s Treadmill'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-8Tt6YNbzDu0/TsFHRyExNsI/AAAAAAAAANU/GYQAlYKQjLE/s72-c/disruptor.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-6574770212091665326</id><published>2011-11-12T12:55:00.001-08:00</published><updated>2011-11-14T08:14:15.679-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reference counting'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematica'/><title type='text'>Real garbage collector characteristics</title><content type='html'>&lt;p&gt;The trade-offs between tracing and reference counting garbage collectors are nicely demonstrated by systems like F# and Mathematica. F# inherits garbage collection from .NET which uses a conventional generational tracing garbage collector with three generations and a Large Object Heap (LOH). Mathematica uses reference counting with language semantics that make it impossible to create cycles in the heap.&lt;/p&gt;&lt;p&gt;The following Mathematica program creates a balanced binary tree 25 levels deep that contains 2&lt;sup&gt;25&lt;/sup&gt; branches stores it in a variable and then mutates the variable back to the empty list:&lt;/p&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/-_zqrDgp1QqA/Tr7d6S7SFBI/AAAAAAAAANI/SAaueNalNZE/s1600/GarbageCollection.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 385px; height: 163px;" src="http://4.bp.blogspot.com/-_zqrDgp1QqA/Tr7d6S7SFBI/AAAAAAAAANI/SAaueNalNZE/s400/GarbageCollection.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5674216574116041746" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Because Mathematica uses reference counting, the act of resetting the variable back to the empty list decrements the reference count for the root of our tree back to zero, causing an avalanche of reference counts in the branches down to the leaves also being decremented back to zero, reclaiming all of the space that was consumed by the tree that is now unreachable. Moreover, Mathematica is serial so all of this work is done on the main thread, blocking everything. Consequently, resetting the variable to the empty list takes a whopping 2.213s.&lt;/p&gt;&lt;p&gt;Surprisingly, although Mathematica has clearly done a lot of work that is presumably involved in releasing the space consumed by the tree it does not actually return any memory to the OS and continues to consume almost half of the entire 32-bit address space on this machine!&lt;/p&gt;&lt;p&gt;This program may be written as follows in F#:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;type t = Leaf | Branch of t * t  let rec deepTree = function   | 0 -&amp;gt; Leaf   | n -&amp;gt; Branch(deepTree(n-1), deepTree(n-1))  let mutable t = deepTree 25  t &amp;lt;- Leaf  System.GC.Collect()&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;In this case, creating the tree takes 10.2s, resetting the tree takes a fraction of a millisecond and explicitly invoking the garbage collector (which actually returns all of the memory back to the OS) takes 0.44s.&lt;/p&gt;&lt;p&gt;This highlights some of the trade-offs involved both in using systems that provide garbage collection as a user and in creating such systems as a developer.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-6574770212091665326?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/6574770212091665326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=6574770212091665326' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6574770212091665326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6574770212091665326'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/11/real-garbage-collector-characteristics.html' title='Real garbage collector characteristics'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-_zqrDgp1QqA/Tr7d6S7SFBI/AAAAAAAAANI/SAaueNalNZE/s72-c/GarbageCollection.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-4844985287412157857</id><published>2011-11-11T15:07:00.001-08:00</published><updated>2011-11-11T16:25:15.292-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reference counting'/><category scheme='http://www.blogger.com/atom/ns#' term='mark compact'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='copying collection'/><category scheme='http://www.blogger.com/atom/ns#' term='mark sweep'/><title type='text'>Classifying garbage collection algorithms</title><content type='html'>&lt;p&gt;Richard Jones' &lt;a href="http://t.co/7OwUU6WJ"&gt;excellent new book about garbage collection&lt;/a&gt; has rekindled my fascination with this important subject. The &lt;a href="http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)"&gt;Wikipedia page about GC&lt;/a&gt; is disappointingly poor quality so it is productive to review the main points here.&lt;/p&gt;&lt;p&gt;GC algorithms are categorized into four main families with production garbage collectors often combining algorithms from different families. The families are copying, mark-sweep, mark-compact and reference counting. The first three are all tracing collectors that work by tracing all reachable values by starting from the global roots (global variables and locals held on the stack).&lt;/p&gt;&lt;p&gt;&lt;b&gt;Copying&lt;/b&gt; collectors allocate into one space and then "evacuate" the reachable heap blocks (called "survivors") into another space before clearing the space they came from. The Cheney semi-space algorithm is the simplest copying collector: it uses two spaces and copies from one to the other and back again. The advantage of copying collection is that many heap-allocated blocks are deallocated simultaneously simply by resetting a pointer. This is ideal when only a small proportion of the allocated values survive a collection. As most values die young, the copying collection algorithm is commonly used for the nursery generation in a generational collector.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Mark sweep&lt;/b&gt; is the oldest garbage collection algorithm (McCarthy 1959) and works by tracing all reachable values and then deallocating all of the remaining unreachable values. This algorithm offers relatively high throughput and can be made incremental (low latency) using Dijkstra's tricolor marking scheme but is (arguably) prone to fragmentation. Consequently, the mark-sweep algorithm is commonly used for the old generation of generational collectors.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Mark compact&lt;/b&gt; traces reachable values and then slides them together. This avoids the problem of fragmentation that can (allegedly) afflict mark-sweep collectors but the throughput of mark-compact collectors is apparently so poor that they are practically unheard of.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Reference counting&lt;/b&gt; works by having each value count the number of references to it. This requires the program to register locally held references by incrementing the reference count of the value referred to and then decrementing it again when the reference is no longer held. This is typically done by decrementing the reference count when the local reference falls out of scope in the source code although liveness analysis can be exploited to find a tighter bound on when a reference is no longer needed. When a reference count is decremented to zero there are no longer any references to the value so it is unreachable and can be deallocated. Interestingly, reference counting is the opposite of tracing because it works by pursuing dropped references rather than by following live references. The advantages of reference counting are its simplicity, determinism in the context of single-threaded programs (multithreaded programs race to decrement and, therefore, deallocate non-deterministically) and that it can easily be made incremental by maintaining a queue of reference counts that have yet to be decremented. The disadvantages are that it leaks cycles and has &lt;a href="http://flyingfrogblog.blogspot.com/2011/01/boosts-sharedptr-up-to-10-slower-than.html"&gt;very poor throughput&lt;/a&gt;. However, cycles can be collected either by a backup tracing collector or by using a specific cycle collector such as the trial deletion algorithm, and throughput can be improved by deferring decrements (although this recovers the disadvantage of unpredictability).&lt;/p&gt;&lt;p&gt;Latency is a big issue in the context of garbage collection so algorithms are also classified according to their latency characteristics. &lt;b&gt;Stop-the-world&lt;/b&gt; algorithms are relatively simple but high latency, incurring arbitrarily-long pause times during which the mutator threads (those running the actual program) make no progress at all. The .NET 4 server GC is an example of a stop-the-world GC in production. GHC also uses a stop-the-world GC. The advantages of stop-the-world garbage collection algorithms are simplicity and high throughput. These GCs often incur pauses of the order of one second, which is totally unacceptable for many soft real-time applications such as visualization, games and (ironically!) servers.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Incremental&lt;/b&gt; GCs break up the work of a full GC and interleave the resulting bits of work in with the execution of the program. For example, OCaml's GC performs a "slice" of the work required to collect the old generation every time the young generation is collected. The advantages of incremental GCs are low latency compared to stop-the-world (e.g. ~10ms pauses with OCaml) and simplicity compared to concurrent GCs.&lt;/p&gt;&lt;p&gt;Today, the term "parallel GC" is used to describe a GC that uses multiple threads to speedup the collection of garbage. The .NET 4 server GC is an example of a parallel GC because it uses one thread per core to mark the heap in parallel. &lt;b&gt;Concurrent&lt;/b&gt; GC means the GC runs at the same time as the mutators. For example, the .NET workstation GC is an example of a concurrent GC in production. Concurrent garbage collectors are further refined into on-the-fly and mostly-concurrent algorithms. An &lt;b&gt;on-the-fly&lt;/b&gt; GC is defined by Jones et al. as one that never suspends more than one mutator at a time (i.e. there is no stop-the-world phase) although I suspect he meant that mutators are suspended independently of each other. Finally, a &lt;b&gt;mostly-concurrent&lt;/b&gt; GC is one that does suspend all mutator threads simultaneously but only for a short period of time and not for an arbitrarily-long GC phase. For example, the .NET workstation GC pauses all mutator threads while the global roots are examined but runs concurrently with them during the marking and sweeping of the whole heap so it is a mostly concurrent garbage collector.&lt;/p&gt;&lt;p&gt;These classifications by family of algorithm and by latency characteristics are the most important ones.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-4844985287412157857?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/4844985287412157857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=4844985287412157857' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4844985287412157857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4844985287412157857'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/11/kinds-of-garbage-collection.html' title='Classifying garbage collection algorithms'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-519800544843492586</id><published>2011-11-03T10:50:00.000-07:00</published><updated>2011-11-03T17:16:54.373-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='profit'/><category scheme='http://www.blogger.com/atom/ns#' term='maximization'/><category scheme='http://www.blogger.com/atom/ns#' term='local optimization'/><category scheme='http://www.blogger.com/atom/ns#' term='monte carlo'/><category scheme='http://www.blogger.com/atom/ns#' term='evolutionary'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><category scheme='http://www.blogger.com/atom/ns#' term='business'/><title type='text'>Applying optimization algorithms to profits</title><content type='html'>&lt;p&gt;As a technology company, we like to apply technical solutions to problems at all levels. Our board of directors even apply technical solutions to the problem of company direction.&lt;/p&gt;&lt;p&gt;Business can be thought of as an optimization algorithm: tweaking stuff and things in order to maximize company profits. Interestingly, we use a number of different kinds of optimization algorithm when dictating the direction of the company.&lt;/p&gt;&lt;p&gt;We begin new product lines based on experience but continue to optimize our products based on customer feedback, trying to solve the problems that are most important to our customers. For example, our &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_numerics/?ffb"&gt;F# for Numerics&lt;/a&gt; library started life as our second attempt at selling libraries to F# users (our first attempt was &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_visualization/?ffb"&gt;F# for Visualization&lt;/a&gt;) and we provided the features we thought would be most useful. Customers inevitably requested more features including both technical features like parallel matrix inversion with arbitrary-precision rational arithmetic but also non-technical features such as licences allowing them to bundle our library in their own commercial products. This approach of incrementally improving products is a kind of &lt;a href="http://en.wikipedia.org/wiki/Local_search_(optimization)"&gt;local optimization&lt;/a&gt; algorithm, like &lt;a href="http://en.wikipedia.org/wiki/Gradient_descent"&gt;gradient descent&lt;/a&gt;. This is a low-risk approach that yields small improvements in profits.&lt;/p&gt;&lt;p&gt;Over the years, we have been commissioned to write many books and reports and have published many books ourselves. We often use content from one successful book as the inspiration for the next. For example,  our 2004 book &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml for Scientists&lt;/a&gt; was surprisingly successful and became the inspiration for our 2006 book F# for Scientists and more recently &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;Visual F# 2010 for Technical Computing&lt;/a&gt;. This is a kind of evolutionary algorithm because the next generation of books are derived from the previous generation and share some of their "DNA" with them. This is a riskier approach with variable results. We take a lot of risks and expect a significant proportion of our new products to fail but every now and then we come up with a new product that ends up earning as much revenue as all of the others combined.&lt;/p&gt;&lt;p&gt;At this level of abstraction, computational algorithms can be used for all sorts of weird and wonderful applications. Doubtless we all use them without even realising it!&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-519800544843492586?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/519800544843492586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=519800544843492586' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/519800544843492586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/519800544843492586'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/11/applying-optimization-algorithms-to.html' title='Applying optimization algorithms to profits'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-807877826750827875</id><published>2011-09-07T01:53:00.001-07:00</published><updated>2011-09-07T02:04:59.524-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='richard jones'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>New book on garbage collection</title><content type='html'>&lt;p&gt;After 15 years, Richard Jones has written a new monograph about garbage collection called &lt;a href="http://gchandbook.org/"&gt;The Garbage Collection Handbook&lt;/a&gt;. This supercedes his previous seminal book on the subject &lt;a href="http://www.cs.kent.ac.uk/people/staff/rej/gcbook/"&gt;Garbage Collection: algorithms for automatic dynamic memory management&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In particular, this new book covers state-of-the-art techniques including parallel, incremental, concurrent and real-time garbage collection algorithms.&lt;/p&gt;&lt;p&gt;I'll post a review as soon as I've read my copy!&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-807877826750827875?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/807877826750827875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=807877826750827875' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/807877826750827875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/807877826750827875'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/09/new-book-on-garbage-collection.html' title='New book on garbage collection'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-5664938474089643176</id><published>2011-03-27T02:27:00.000-07:00</published><updated>2011-05-04T16:13:31.763-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='fsharp'/><category scheme='http://www.blogger.com/atom/ns#' term='disadvantages'/><category scheme='http://www.blogger.com/atom/ns#' term='limitations'/><category scheme='http://www.blogger.com/atom/ns#' term='advantages'/><title type='text'>Pros and cons of OCaml</title><content type='html'>&lt;p&gt;The advantages and disadvantages of the &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt; programming language.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Pros:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;More powerful type inference than any other language: &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt; even infers union and class types!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Powerful module system lets you parameterize modules over other  modules easily and safely with full compile-time checking and minimal  run-time overhead.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Structural typing of modules, polymorphic variants and classes  improves brevity, closing the gap with dynamic languages, but can  obfuscate error messages.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Powerful integrated macro system lets you alter the language's syntax on-the-fly and write parsers quickly and easily.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Good serial performance from the x64 code gen.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Easy-to-use REPL.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Lots of high-quality tools and libraries.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;   &lt;p&gt;Cons:&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;p&gt;No overloading can make numerical code over many different types (e.g. complex numbers, vectors and matrices) tedious.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Poor multicore support means poor performance on today's computers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Some basic functionality missing (e.g. no 32-bit floats, no &lt;code&gt;try&lt;/code&gt;..&lt;code&gt;finally&lt;/code&gt; construct).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Some basic functionality is very inefficient (e.g. 32-bit ints).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Poor floating point performance from the x86 code gen.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;16MB limit on strings and arrays on 32-bit systems.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;No way to override equality, comparison and hashing for new types and no way to catch errors created by this when the default structural versions are not applicable. Type classes are a solution to the former problem and equality types are a solution to the latter.&lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;No value types means more memory use and worse performance in some important situations (e.g. filling a hash table with &lt;code&gt;float&lt;/code&gt; keys and values in &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt; is 17× slower than &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-5664938474089643176?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/5664938474089643176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=5664938474089643176' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5664938474089643176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5664938474089643176'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/03/pros-and-cons-of-ocaml.html' title='Pros and cons of OCaml'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-5248930196376614617</id><published>2011-03-13T10:31:00.000-07:00</published><updated>2011-03-13T10:48:34.164-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='numerical recipes'/><category scheme='http://www.blogger.com/atom/ns#' term='numerical methods'/><title type='text'>Alternatives to Numerical Recipes</title><content type='html'>&lt;p&gt;The &lt;a href="http://www.jpl.nasa.gov/"&gt;Jet Propulsion Laboratory at Nasa&lt;/a&gt; once hosted an interesting web page listing better alternatives to the infamous book Numerical Recipes. Here is a copy courtesy of &lt;a href="http://www.archive.org/web/web.php"&gt;The Wayback Machine&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;There is no single alternative to Numerical Recipes.  The authors of Numerical Recipes provide a superficial overview of a large amount of material in a small volume.  In order to do so, they made many unfortunate compromises.&lt;/p&gt;&lt;p&gt;It is naïve to hope that every computational problem can be solved by a simple procedure that can be described in a few pages of chatty prose, and using a page or two of Fortran or C code.  Today's ambitions for correctness, accuracy, precision, stability, "robustness", efficiency, etc. demand sophisticated codes developed by experts with deep understanding of their disciplines.  We have long ago outgrown the capabilities of the simplistic approaches of 30 years ago.&lt;/p&gt;&lt;p&gt;Steve Sullivan has constructed a &lt;a href="http://replay.waybackmachine.org/20021015200910/ftp://rtfm.mit.edu/pub/usenet/news.answers/num-analysis/faq/part1"&gt;FAQ (Frequently Asked Questions)&lt;/a&gt; list on numerical analysis. The size of the list will give you some idea of the scope of the field.  Some books are reviewed in section q165.&lt;/p&gt;&lt;p&gt;It would be unproductive to try to list all the excellent textbooks on numerical analysis.  A few of them are (in alphabetical order of primary author):&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Kendall Atkinson, &lt;b&gt;Numerical Analysis&lt;/b&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ward Cheney and David Kincaid, &lt;b&gt;Numerical Mathematics and Computing&lt;/b&gt;, Brooks-Cole (Third edition, 1994).  Aharon Naiman has prepared &lt;a href="http://replay.waybackmachine.org/20021015200910/http://hobbes.jct.ac.il/%7Enaiman/na"&gt;slides for a series of lectures&lt;/a&gt; he teaches at Jerusalem College of Technology using this text.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;George Forsythe, Michael Malcolm and Cleve Moler, &lt;b&gt;Computer Methods for Mathematical Computations&lt;/b&gt;, Prentice-Hall (1977).  This book is probably out of print.  It is a predecessor to the book by Kahaner et. al., and written in a similar style.  It is less comprehensive than the newer work.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Francis B. Hildebrand, &lt;b&gt;Introduction to Numerical Analysis&lt;/b&gt;, McGraw-Hill (1956, 1974), Dover (1987 0-486-65363-3).  This is one of the best books ever written on numerical analysis.  It's out-of-date in some areas, most notably in Least Squares computation.  Hildebrand has an engaging and transparent style of exposition, similar to Press et. al.  This book is, however, a mathematically sound reference to material of the same era as presented in much of &lt;b&gt;Numerical Recipes&lt;/b&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;David Kahaner, Cleve Moler and John Nash, &lt;b&gt;Numerical Methods and Software&lt;/b&gt;, Prentice-Hall (1989). ISBN 0-13-627258-4. This book is probably closest in style to &lt;b&gt;Numerical Recipes&lt;/b&gt;, but was written by practitioners in the field, rather then by experts in a different field.&lt;br /&gt;Diskette included.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;John H. Mathews, &lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.prenhall.com/books/esm_0136249906.html"&gt;&lt;b&gt;Numerical Methods: for Mathematics, Science &amp;amp; Engineering, 2nd Ed.&lt;/b&gt;&lt;/a&gt;, ISBN 0-13-624990-6  and 0-13-625047-5, &lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.prenhall.com/"&gt;Prentice Hall Inc.&lt;/a&gt; (1992).   With purchase of this book free software is available from the following links:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://replay.waybackmachine.org/20021015200910/ftp://ftp.mathworks.com/pub/books/mathews/c"&gt;ftp://ftp.mathworks.com/pub/books/mathews/c&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://replay.waybackmachine.org/20021015200910/ftp://ftp.mathworks.com/pub/books/mathews/fortran"&gt;ftp://ftp.mathworks.com/pub/books/mathews/fortran&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://replay.waybackmachine.org/20021015200910/ftp://ftp.mathworks.com/pub/books/mathews/pascal"&gt;ftp://ftp.mathworks.com/pub/books/mathews/pascal&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://replay.waybackmachine.org/20021015200910/ftp://ftp.mathworks.com/pub/books/mathews/matlab"&gt;ftp://ftp.mathworks.com/pub/books/mathews/matlab&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.mathsource.com/cgi-bin/MathSource/Publications/BookSupplements/Mathews-1997/0208-831"&gt;NUMERICAL METHODS: Mathematica 3.0 Notebooks&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;John H. Mathews and Russell W. Howell,&lt;br /&gt;&lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.jbpub.com/"&gt;&lt;b&gt;COMPLEX ANALYSIS: for Mathematics and Engineering, Third Edition, 1997&lt;/b&gt;&lt;/a&gt;, ISBN 0-7637-0270-6.&lt;br /&gt;With purchase of this book, &lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.jbpub.com/disks/index.htm"&gt; free software is available.&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Zdzislaw Meglicki has posted &lt;a href="http://replay.waybackmachine.org/20021015200910/http://noir.ovpit.indiana.edu/B673/"&gt;the text for a course on advanced scientific computing&lt;/a&gt; at Indiana University.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;G. W. "Pete" Stewart posted the following in&lt;br /&gt;&lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.netlib.org/na-net/na_home.html"&gt;na-net&lt;/a&gt;:&lt;br /&gt;"I have recently published a book entitled `Afternotes on Numerical Analysis'...  It is a series of 22 lectures on elementary numerical analysis.  The notes themselves were prepared after the lectures were given and are an accurate snapshot of what went on in class.  Although they are no substitute for a full-blown numerical analysis textbook, many people have found them a useful supplement to a first course.  The book is published by SIAM.  For further information contact service@siam.org." and on 2 Jan 1997:&lt;p&gt;I have just completed a new set of afternotes and have posted them on the web. The original afternotes were based on an advanced undergraduate course taught at the University of Maryland.  The present notes are based on the follow-up graduate course.  The topics treated are approximation\,---\,discrete and continuous\,---\,linear and quadratic splines, eigensystems, and Krylov sequence methods.  The notes conclude with two little lectures on classical iterative methods and nonlinear equations&lt;/p&gt;&lt;p&gt;The notes may be obtained by anonymous ftp at thales.cs.umd.edu in /pub/afternotes or by browsing my homepage&lt;br /&gt; &lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.cs.umd.edu/%7Estewart/"&gt;http://www.cs.umd.edu/~stewart/&lt;/a&gt;.&lt;br /&gt; I will be grateful for any comments, corrections, or suggestions.&lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;There are excellent texts and reference works that focus on narrow portions of&lt;br /&gt;the discipline of numerical analysis.  Consider, for example:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Gene H. Golub and Charles F. Van Loan, &lt;b&gt;Matrix Computations&lt;/b&gt;, Johns Hopkins (first edition 1983, second edition 1989, third edition 1996).  ISBN 0-8018-5413-X (0-8018-5414-8 paper).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ernst Hairer, Syvert Paul Nørsett, Gerhard Wanner, &lt;b&gt;Solving Ordinary Differential Equations I: Nonstiff Problems&lt;/b&gt;, Springer-Verlag (1987 3-540-17145-2 0-387-17145-2).  A second edition has appeared but the ISBN's here are for the first.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ernst Hairer, Gerhard Wanner, &lt;b&gt;Solving Ordinary Differential Equations II: Stiff  and Differential-Algebraic Problems&lt;/b&gt;, Springer-Verlag (1991: 3-540-53775-9 and 0-387-53775-9; 1996: 3-540-60452-9).  This book and the previous one are highly regarded.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Charles L. Lawson and Richard J. Hanson, &lt;b&gt;Solving Least Squares Problems&lt;/b&gt;, Prentice-Hall (first edition 1974), SIAM Press (second edition 1995) ISBN 0-89871-356-0.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Philip J. Davis and Philip Rabinowitz, &lt;b&gt;Methods of Numerical Integration&lt;/b&gt;, Academic Press (second edition 1984) ISBN 0-12-206360-0.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ingrid Daubechies, &lt;b&gt;Ten Lectures on Wavelets&lt;/b&gt;, SIAM Press.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Jorge J. Moré and Stephen J. Wright, &lt;i&gt;Optimization Software Guide&lt;/i&gt;, &lt;b&gt;Frontiers in Applied Mathematics 14&lt;/b&gt;, Society for Industrial and Applied Mathematics (1993).  About evenly divided between algorithms and software, both public-domain and commercial.  (This book actually covers a fair amount of the content of &lt;b&gt;Numerical Recipes&lt;/b&gt;, especially those parts that the authors of NR deemed too complex to do well.)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Spaeth, &lt;b&gt;Mathematical Algorithms for Linear Regression&lt;/b&gt; (1987).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;If you have been using &lt;b&gt;Numerical Recipes&lt;/b&gt; for software, we recommend that&lt;br /&gt;you contact the computing professionals in your organization.  For JPL users, you can contact the &lt;a href="http://replay.waybackmachine.org/20021015200910/http://math.jpl.nasa.gov/humans.html"&gt;Computational Mathematics Subgroup&lt;/a&gt;, or obtain the &lt;a href="http://replay.waybackmachine.org/20021015200910/http://math.jpl.nasa.gov/index.html"&gt;Math77 and&lt;i&gt; mathc90&lt;/i&gt;&lt;/a&gt; libraries of mathematical software directly.  There is also a substantial amount of &lt;a href="http://replay.waybackmachine.org/20021015200910/http://math.jpl.nasa.gov/nr/other-sw.html"&gt;software and information about software&lt;/a&gt; on-line.&lt;p&gt;For one-of-a-kind computations, we recommend &lt;a href="http://replay.waybackmachine.org/20021015200910/http://www.mathworks.com/"&gt;MATLAB (The MathWorks, Inc.)&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-5248930196376614617?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/5248930196376614617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=5248930196376614617' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5248930196376614617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5248930196376614617'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/03/alternatives-to-numerical-recipes.html' title='Alternatives to Numerical Recipes'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-5364037152250373799</id><published>2011-02-23T14:11:00.000-08:00</published><updated>2011-02-23T16:33:26.601-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Scala's premature release</title><content type='html'>&lt;p&gt;Back in August 2010, Martin Odersky raised eyebrows by stating that "&lt;a href="http://blog.fogus.me/2010/08/06/martinodersky-take5-tolist/"&gt;Scala is foremost an industrial language&lt;/a&gt;". We &lt;a href="http://flyingfrogblog.blogspot.com/2010/08/scala-is-foremost-industrial-language.html"&gt;commented&lt;/a&gt; on this triumph of hope over reality at the time, citing Scala's poor IDE support as a major headache for industrial users that had deterred us from adopting this academically-interesting programming language.&lt;/p&gt;&lt;p&gt;This rookie mistake of marketing a product months before it is ready is all too common. Several of our young client companies made the same mistake. One had even been paying an entire sales division not only salaries but bonuses for over a year before their first product was released!&lt;/p&gt;&lt;p&gt;The problem is not just the wasted marketing effort but that potential customers are deterred by their bad experiences with the immature product. This is reflected in Jonathan Edwards' recent article "&lt;a href="http://alarmingdevelopment.org/?p=562"&gt;Switching to Plan J&lt;/a&gt;", where he writes:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;"&lt;i&gt;My experiment with Scala is not working out. It’s just not ready for prime time...&lt;/i&gt;" - Jonathan Edwards&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;and others echo the sentiment:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;"&lt;i&gt;I’ve found exactly the same thing...&lt;/i&gt;" - Nat&lt;/blockquote&gt;&lt;blockquote&gt;"&lt;i&gt;I agree with every point you made in this article... Tools are awful, even though years have been spent developing them.&lt;/i&gt;" - Mark&lt;/blockquote&gt;&lt;blockquote&gt;"...&lt;i&gt;&lt;a href="http://lambda-the-ultimate.org/node/4186#comment-64411"&gt;plagued by continuous problems&lt;/a&gt;&lt;/i&gt;..." - Roy Batty&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Martin Odersky now says that he is "&lt;a href="http://lambda-the-ultimate.org/node/4186#comment-64414"&gt;painfully aware of the Eclipse issues&lt;/a&gt;" and Scala Solutions are working to produce reliable IDE support for Scala but he also admits that Emacs has been his IDE of choice for Scala development.&lt;/p&gt;&lt;p&gt;Hopefully the potential users who have been disappointed by today's Scala will try the language again once a first attempt has been made to address core issues like the reliability of the IDE support.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-5364037152250373799?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/5364037152250373799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=5364037152250373799' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5364037152250373799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5364037152250373799'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/02/scalas-premature-release.html' title='Scala&apos;s premature release'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-1127948303689189344</id><published>2011-02-09T10:16:00.000-08:00</published><updated>2011-02-09T10:23:17.044-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='loc'/><category scheme='http://www.blogger.com/atom/ns#' term='lines of code'/><title type='text'>Size of industrial F# code bases</title><content type='html'>&lt;p&gt;Almost exactly a year ago, we published &lt;a href="http://flyingfrogblog.blogspot.com/2010/02/sizes-of-industrial-ocaml-and-f-code.html"&gt;a blog post&lt;/a&gt; stating that we had 345kLOC of production OCaml code and 171kLOC of production F# code. Today, we have 261kLOC of production F# code!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-1127948303689189344?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/1127948303689189344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=1127948303689189344' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1127948303689189344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1127948303689189344'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/02/size-of-industrial-f-code-bases.html' title='Size of industrial F# code bases'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-702398816358410884</id><published>2011-01-09T04:29:00.000-08:00</published><updated>2011-01-09T05:45:36.521-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mark region'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Sweeping 700× faster</title><content type='html'>&lt;p&gt;Our initial experiments using the new garbage collector design indicate that it dramatically improves the performance of the slowest GC phase (sweeping) as expected, to the extent that it brings the overall performance of our C++ prototype within 10% of OCaml without introducing any of the overheads of generational garbage collection:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_NMRkpon4Ps0/TSm3HctgQDI/AAAAAAAAALU/MSvc1enLaK4/s1600/AllocatorPerformance.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 284px;" src="http://1.bp.blogspot.com/_NMRkpon4Ps0/TSm3HctgQDI/AAAAAAAAALU/MSvc1enLaK4/s400/AllocatorPerformance.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5560176553559605298" /&gt;&lt;/a&gt;&lt;p&gt;Moreover the algorithm is very simple and, in particular, parallel and concurrent variants should be much easier to design with this style of collector than with generational collectors because regions are a suitable granularity.&lt;/p&gt;&lt;p&gt;The sweep phase of the GC accounted for around a third of the total running time of the entire program using the traditional algorithm with allocated and free lists, with each sweep taking around 70µs. Using the new bitwise algorithm, the sweep phase takes just  100ns and accounts for just 0.7% of the total running time of the program.&lt;/p&gt;&lt;p&gt;Our prototype mark region collector using a fake marking phase is now between 2 and 10% slower than OCaml without having sacrificed either its better performance on other benchmarks or its multicore capability. However, our new design has increased the cost of both allocation and marking. Although they accounted for a tiny proportion of the total running time, it remains to be seen whether or not this new GC algorithm will be faster than a traditional generational collector in this best-case scenario for generational collection when it is implemented in a real VM. In particular, the &lt;a href="http://flyingfrogblog.blogspot.com/2009/03/current-shadow-stack-overheads-in-hlvm.html"&gt;overheads of HLVM's current shadow stack&lt;/a&gt; may well make it slower.&lt;/p&gt;&lt;p&gt;Our collection strategy also captures the benefits of Appel's semi-generational collection algorithm. Appel's algorithm compacted nursery survivors to one end of the nursery and used the remaining space as a smaller nursery repeatedly until the entire nursery was full of reachable values that were then promoted to the old generation. Our region-based collector can allow each thread to sweep its own region locally, independently of all other regions and cores. This also leads to the same non-linearity that makes Appel's algorithm so effective but without the overheads of copying. Using regions containing 62 blocks each 64 bytes long, local sweeping increased the number of allocations performed before a new region was required from 62 to a whopping 3,000 allocations. Obtaining a new region requires synchronization, so this simple improvement has reduced the rate of synchronizations by around a factor of 50. With 8-byte regions, the 11-queens problem can be solved with a single region and, therefore, without any contention at all between threads.&lt;/p&gt;&lt;p&gt;Therefore, we believe our new GC design will allow us to make HLVM competitively performant on functional benchmarks like this without losing its substantial advantages on imperative code, where it is often several times faster than OCaml.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-702398816358410884?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/702398816358410884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=702398816358410884' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/702398816358410884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/702398816358410884'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/01/sweeping-700-faster.html' title='Sweeping 700× faster'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_NMRkpon4Ps0/TSm3HctgQDI/AAAAAAAAALU/MSvc1enLaK4/s72-c/AllocatorPerformance.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-7624815485709455418</id><published>2011-01-08T06:12:00.000-08:00</published><updated>2011-01-12T14:51:36.420-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mark region'/><category scheme='http://www.blogger.com/atom/ns#' term='bitvector'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='bitwise'/><category scheme='http://www.blogger.com/atom/ns#' term='allocation'/><title type='text'>The importance of locality and sparsity in memory management</title><content type='html'>&lt;p&gt;Our previous articles describing the &lt;a href="http://flyingfrogblog.blogspot.com/2010/12/when-generational-gc-goes-bad.html"&gt;disadvantages of generational garbage collection&lt;/a&gt; and &lt;a href="http://flyingfrogblog.blogspot.com/2010/12/towards-mark-region-gc-for-hlvm.html"&gt;our prototype mark-region memory management system designed for HLVM&lt;/a&gt; originally showed that region-based allocation and deallocation has the potential to be only 4-20% slower than OCaml's generational collector. However, &lt;a href="http://flyingfrogblog.blogspot.com/2011/01/boosts-sharedptr-up-to-10-slower-than.html"&gt;our more recent work&lt;/a&gt; that was designed to be more realistic by deferring deallocations to bulk GC cycles was significantly slower, around twice as slow as OCaml.&lt;/p&gt;&lt;p&gt;There are several differences between the stack-based deallocation scheme used in the first benchmark and the GC-like deallocation scheme used in the second benchmark that have the potential to account for this performance degradation:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The mock GC introduced mark bytes into the allocated values and marked them as unreachable when they fell out of scope in the mutator.&lt;/li&gt;&lt;li&gt;The mock GC allocated by popping a reference of the top of a region's free list.&lt;/li&gt;&lt;li&gt;The mock GC deallocated by pushing a reference onto the free list of the reference's region.&lt;/li&gt;&lt;li&gt;The mock GC added an "allocated list" that is used to record everything that has been allocated.&lt;/li&gt;&lt;li&gt;Upon deallocation, the mock GC removed a reference from the allocated list by overwriting it with the last element and reducing the length of the allocated list by one.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The overhead of the new "mark phase" that marks values as unreachable when they fall out of scope is minimal. The mark phase in HLVM's real GC accounts for less than 2% of the total running time of this benchmark and it does significantly more work (traversing the shadow stack) than the mark phase in this benchmark.&lt;/p&gt;&lt;p&gt;Using the free list as a stack would cause subsequent allocations to be contiguous in memory if and only if the free list happens to be ordered, i.e. allocations and deallocations are in LIFO order. This was the case in the first benchmark but not the second.&lt;/p&gt;&lt;p&gt;Upon collection, the allocated list was traversed sequentially. However, the way in which references were removed from the allocated list may well have been the critical design flaw. Specifically, moving an the element from the back of the allocated list into the middle, to overwrite a removed element changes the order of the list slightly. We suspected that the disorder would accumulate over time, destroying the locality of the references in the allocated list. Consequently, a sequential traversal of the allocated list is likely to have been of little benefit because the subsequent elements of the allocated list would have referenced random locations. Moreover, that disorder would have been passed on to the free lists, which would have seen values freed in random order rather than sequentially.&lt;/p&gt;&lt;p&gt;We had speculated that sparsity was largely responsible for the remaining performance gap between OCaml and all of the strategies based upon per-value deallocation because OCaml's generational GC is able to sweep runs of contiguously-allocated values from the nursery generation in constant time. On the basis of this, we predicted that a derivative of mark-region capable of deallocating contiguous runs of values from a region might get significantly closer to OCaml's performance on this benchmark. In particular, the performance profile of our prototype indicates that 18% of the total time is spent allocating and 17% is spent collecting. Furthermore, the L2 cache is around 50% slower than the L1 cache on this machine so the performance of the mutator might be 50% worse due to poor locality of reference in the second benchmark. These figures suggest that improving locality might double performance and, therefore, make our solution as fast as OCaml.&lt;/p&gt;&lt;p&gt;To answer some of our questions, we wrote a simulation of the prototype (!) in the &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F# programming language&lt;/a&gt; and used it to gather relevant statistics. This proved to be extremely successful and led to several major insights.&lt;/p&gt;&lt;p&gt;Firstly, values die over time so longer gaps between GC cycles means a higher proportion of unreachable values. The following graph illustrates the relationship between the number of allocations performed between collections and the proportion of values that remain reachable:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_NMRkpon4Ps0/TSiWHTACxvI/AAAAAAAAALE/M2f0ckNcoW4/s1600/SweepingEfficiency.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 238px;" src="http://2.bp.blogspot.com/_NMRkpon4Ps0/TSiWHTACxvI/AAAAAAAAALE/M2f0ckNcoW4/s400/SweepingEfficiency.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5559858792092583666" /&gt;&lt;/a&gt;&lt;p&gt;If GC cycles are separated by at least 300 allocations then more than half of the allocated values become unreachable and are swept. Therefore, we can optimize the allocated list operations under the assumption that most of the elements of the list will not survive a GC cycle.&lt;/p&gt;&lt;p&gt;Secondly, we found that the algorithm used to remove an element from the allocated list does indeed dominate the locality and, therefore, the performance of the entire program. The following graph illustrates the probability density of deallocations as a function of the length of the run of contiguously-allocated values that a value is in:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_NMRkpon4Ps0/TSiXEVZELzI/AAAAAAAAALM/9NEOJjO2rxo/s1600/SparsityOfDeallocations.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 238px;" src="http://4.bp.blogspot.com/_NMRkpon4Ps0/TSiXEVZELzI/AAAAAAAAALM/9NEOJjO2rxo/s400/SparsityOfDeallocations.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5559859840706424626" /&gt;&lt;/a&gt;&lt;p&gt;These results show that the original algorithm for removing references from the allocated list led to &lt;b&gt;45%&lt;/b&gt; of values being deallocated alone and significantly fewer being deallocated in contiguous runs. Therefore, it is clear that the original algorithm was indeed destroying locality when it reordered the references in the allocated lists.&lt;/p&gt;&lt;p&gt;In contrast, removing values from the allocated list using the order-preserving sliding compaction retained locality. In that case, only &lt;b&gt;0.02%&lt;/b&gt; of values were deallocated alone. In fact, the new algorithm is so good at preserving locality that &lt;i&gt;values are more likely to be deallocated with a few neighbors than alone&lt;/i&gt;. Specifically, values are 4× more likely to be deallocated as part of a run of 23 contiguously-allocated values than they are to be deallocated alone.&lt;/p&gt;&lt;p&gt;These new results lend credence to our conjecture that exploiting sparsity by deallocating contiguous runs of values rather than individual values is the key to achieving performance comparable to that of a generational GC. However, we also now know that this will only be possible if the allocation-collection cycle preserves locality as much as possible.&lt;/p&gt;&lt;p&gt;The simplest way to preserve the order of allocations and exploit sparse deallocations is to side step the problem by changing the data structures involved:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Replace the free list with a bitvector.&lt;/li&gt;&lt;li&gt;Replace the mark bits in each value with a per-region mark bitvector.&lt;/li&gt;&lt;li&gt;Replace the allocated list with queues of full and non-full regions.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;With 512 bits in a cache line, we can reserve the first cache line of each region to use as a bitvector for the entire region because we previously found that regions containing around this many values give near-optimal performance. Allocating from a region is then a matter of finding the first (un)set bit in the bitvector and the associated location, flipping the bit and returning the location. A contiguous sequence of values can be deallocated from a region by computing and applying a bitmask to the bitvector.&lt;/p&gt;&lt;p&gt;With regions conveying where allocated values are, there is no longer any need for an explicit allocated list. Therefore, the allocated list may be replaced with a global queue of regions. When a local region is filled it is enqueued on the global queue of full-regions and a region is dequeued from the global queue of non-full regions or freshly allocated if there are no non-full regions in the global queue. When a GC cycle occurs, the global regions are dequeued, swept and enqueued again on the appropriate queue, i.e. if a full region becomes non-full then it changes queues.&lt;/p&gt;&lt;p&gt;Incredibly, sweeping a region is now as simple as applying bitwise operations to the allocated- and marked-bitvectors in order to remove unmarked locations from the allocated bitvector.&lt;/p&gt;&lt;p&gt;With this new design, the operations that limited the performance of the old design will now be substantially faster and the locality of reference for the mutator threads will be greatly improved.&lt;/p&gt;&lt;p&gt;We are currently prototyping this new design. As we shall see in a future post, this new GC algorithm not only naturally lends itself to both parallelism and concurrency but is also almost a drop-in replacement for HLVM's current memory management subsystem.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-7624815485709455418?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/7624815485709455418/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=7624815485709455418' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/7624815485709455418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/7624815485709455418'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/01/importance-of-locality-and-sparsity-in.html' title='The importance of locality and sparsity in memory management'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_NMRkpon4Ps0/TSiWHTACxvI/AAAAAAAAALE/M2f0ckNcoW4/s72-c/SweepingEfficiency.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-140739832477800085</id><published>2011-01-05T04:38:00.000-08:00</published><updated>2011-01-05T04:50:19.616-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='numeric tower'/><category scheme='http://www.blogger.com/atom/ns#' term='paul graham'/><category scheme='http://www.blogger.com/atom/ns#' term='accumulator generator'/><title type='text'>Paul Graham's accumulator generator</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; border-collapse: collapse; font-size: 14px; line-height: 18px; "&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; clear: both; word-wrap: break-word; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;span&gt;&lt;span&gt;Paul Graham once published &lt;a href="http://paulgraham.com/accgensub.html"&gt;an article&lt;/a&gt; about what he called "accumulator generators". This problem requires the existence of an unspecified numeric tower. Lisp happens to have one and it happens to be adequate for Paul Graham's examples.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; clear: both; word-wrap: break-word; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;span&gt;&lt;span&gt;You can implement a numeric tower in F# either using a union type (like&lt;/span&gt;&lt;/span&gt; &lt;code style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 1px; padding-right: 5px; padding-bottom: 1px; padding-left: 5px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-position: initial initial; background-repeat: initial initial; "&gt;type number = Int of int | Float of float&lt;/code&gt;) or by boxing everything. The following solution uses the latter approach:&lt;/p&gt;&lt;pre class="lang-ml prettyprint" style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; overflow-x: auto; overflow-y: auto; width: auto; max-height: 600px; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;code style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;let&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; add &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;x&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;:&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; obj&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;y&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;:&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; obj&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;match&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;,&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; y &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;with&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;|&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; int &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; m&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;),&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; int &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; n&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;-&gt;&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; box&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;m&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;+&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;n&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;|&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; int &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; n&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;),&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; float &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;|&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; float &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;),&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; int &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; n&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;-&gt;&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; box&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;+&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; float n&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;|&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; float &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;),&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(:?&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; float &lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;as&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; y&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;-&gt;&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; box&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;+&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; y&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;|&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; _ &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;-&gt;&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; failwith &lt;/span&gt;&lt;span class="str" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;"Run-time type error"&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;let&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; acc x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;let&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; ref x&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;fun&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;y&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;:&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; obj&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;-&gt;&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt; x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;:=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; add &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;!&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;x y&lt;br /&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;!&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;x&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;let&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;:&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; obj &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;-&gt;&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; _ &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; acc&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;box &lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;1&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;do&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;box &lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;5&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;do&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; acc&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;box &lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;3&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;do&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; printfn &lt;/span&gt;&lt;span class="str" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;"%A"&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;x&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;box &lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;2.3&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;))&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; clear: both; word-wrap: break-word; background-position: initial initial; background-repeat: initial initial; "&gt;However, numeric towers are of little use in general purpose programming and usually do more harm than good. Trying to learn from these kinds of challenges can do more harm than good. The real question is: why we do not want a numeric tower, do not want to box and do not want run-time type promotion?&lt;/p&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; clear: both; word-wrap: break-word; background-position: initial initial; background-repeat: initial initial; "&gt;In other words, why didn't we just write:&lt;/p&gt;&lt;pre class="lang-ml prettyprint" style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; overflow-x: auto; overflow-y: auto; width: auto; max-height: 600px; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;code style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;let&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;1&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;let&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;+&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;5&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;ignore&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;(&lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;3&lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;)&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: rgb(0, 0, 139); background-position: initial initial; background-repeat: initial initial; "&gt;let&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;=&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; float x &lt;/span&gt;&lt;span class="pun" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;+&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt; &lt;/span&gt;&lt;span class="lit" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: maroon; background-position: initial initial; background-repeat: initial initial; "&gt;2.3&lt;/span&gt;&lt;span class="pln" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; clear: both; word-wrap: break-word; background-position: initial initial; background-repeat: initial initial; "&gt;We know the type of &lt;code style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 1px; padding-right: 5px; padding-bottom: 1px; padding-left: 5px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-position: initial initial; background-repeat: initial initial; "&gt;x&lt;/code&gt; at every step. Every number is stored unboxed. And we know that this code cannot produce a run-time type error.&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-140739832477800085?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/140739832477800085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=140739832477800085' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/140739832477800085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/140739832477800085'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/01/paul-grahams-accumulator-generator.html' title='Paul Graham&apos;s accumulator generator'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-4190817419125695600</id><published>2011-01-04T05:15:00.000-08:00</published><updated>2011-01-05T01:05:23.073-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='throughput'/><category scheme='http://www.blogger.com/atom/ns#' term='io'/><title type='text'>IO throughput: Haskell vs F#</title><content type='html'>&lt;p&gt;Many applications require the ability to churn through gigabytes of data. In such cases, high IO throughput is valuable. This article examines high-throughput IO in the &lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt; and &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; programming languages. The &lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt; solutions use the &lt;a href="http://hackage.haskell.org/packages/archive/bytestring/0.9.1.8/doc/html/Data-ByteString.html"&gt;ByteString&lt;/a&gt; library and the &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; solutions use ordinary .NET 4 IO.&lt;/p&gt;&lt;p&gt;An eager &lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt; solution that loads the entire file into memory may be written as follows:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#066;&amp;#105;&amp;#116;&amp;#115;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#066;&amp;#121;&amp;#116;&amp;#101;&amp;#083;&amp;#116;&amp;#114;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#097;&amp;#115;&amp;#032;&amp;#066;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#065;&amp;#114;&amp;#103;&amp;#115;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#066;&amp;#046;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#070;&amp;#105;&amp;#108;&amp;#101;&amp;#032;&amp;#046;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#046;&amp;#104;&amp;#101;&amp;#097;&amp;#100;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&amp;#032;&amp;#046;&amp;#032;&amp;#066;&amp;#046;&amp;#102;&amp;#111;&amp;#108;&amp;#100;&amp;#108;&amp;#032;&amp;#120;&amp;#111;&amp;#114;&amp;#032;&amp;#048;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;A lazy alternative that loads parts of the file on-demand may be written as follows:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#066;&amp;#105;&amp;#116;&amp;#115;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#066;&amp;#121;&amp;#116;&amp;#101;&amp;#083;&amp;#116;&amp;#114;&amp;#105;&amp;#110;&amp;#103;&amp;#046;&amp;#076;&amp;#097;&amp;#122;&amp;#121;&amp;#032;&amp;#097;&amp;#115;&amp;#032;&amp;#066;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#065;&amp;#114;&amp;#103;&amp;#115;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#066;&amp;#046;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#070;&amp;#105;&amp;#108;&amp;#101;&amp;#032;&amp;#046;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#046;&amp;#104;&amp;#101;&amp;#097;&amp;#100;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&amp;#032;&amp;#046;&amp;#032;&amp;#066;&amp;#046;&amp;#102;&amp;#111;&amp;#108;&amp;#100;&amp;#108;&amp;#032;&amp;#120;&amp;#111;&amp;#114;&amp;#032;&amp;#048;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;An eager &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; version can simply call the ReadAllBytes function to load the entire file:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#073;&amp;#079;&amp;#046;&amp;#070;&amp;#105;&amp;#108;&amp;#101;&amp;#046;&amp;#082;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#108;&amp;#108;&amp;#066;&amp;#121;&amp;#116;&amp;#101;&amp;#115;&amp;#032;&amp;#102;&amp;#105;&amp;#108;&amp;#101;&amp;#013;&amp;#010;&amp;#124;&amp;#062;&amp;#032;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#046;&amp;#102;&amp;#111;&amp;#108;&amp;#100;&amp;#032;&amp;#040;&amp;#094;&amp;#094;&amp;#094;&amp;#041;&amp;#032;&amp;#048;&amp;#117;&amp;#121;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;An on-demand alternative simply opens the file and calls ReadByte on a buffered stream in a loop until the end of the file is reached:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#117;&amp;#115;&amp;#101;&amp;#032;&amp;#115;&amp;#116;&amp;#114;&amp;#101;&amp;#097;&amp;#109;&amp;#032;&amp;#061;&amp;#032;&amp;#110;&amp;#101;&amp;#119;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#073;&amp;#079;&amp;#046;&amp;#070;&amp;#105;&amp;#108;&amp;#101;&amp;#083;&amp;#116;&amp;#114;&amp;#101;&amp;#097;&amp;#109;&amp;#040;&amp;#102;&amp;#105;&amp;#108;&amp;#101;&amp;#044;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#073;&amp;#079;&amp;#046;&amp;#070;&amp;#105;&amp;#108;&amp;#101;&amp;#077;&amp;#111;&amp;#100;&amp;#101;&amp;#046;&amp;#079;&amp;#112;&amp;#101;&amp;#110;&amp;#041;&amp;#013;&amp;#010;&amp;#117;&amp;#115;&amp;#101;&amp;#032;&amp;#115;&amp;#116;&amp;#114;&amp;#101;&amp;#097;&amp;#109;&amp;#032;&amp;#061;&amp;#032;&amp;#110;&amp;#101;&amp;#119;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#073;&amp;#079;&amp;#046;&amp;#066;&amp;#117;&amp;#102;&amp;#102;&amp;#101;&amp;#114;&amp;#101;&amp;#100;&amp;#083;&amp;#116;&amp;#114;&amp;#101;&amp;#097;&amp;#109;&amp;#040;&amp;#115;&amp;#116;&amp;#114;&amp;#101;&amp;#097;&amp;#109;&amp;#041;&amp;#013;&amp;#010;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#114;&amp;#101;&amp;#099;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#110;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#098;&amp;#032;&amp;#061;&amp;#032;&amp;#115;&amp;#116;&amp;#114;&amp;#101;&amp;#097;&amp;#109;&amp;#046;&amp;#082;&amp;#101;&amp;#097;&amp;#100;&amp;#066;&amp;#121;&amp;#116;&amp;#101;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#098;&amp;#032;&amp;#062;&amp;#061;&amp;#032;&amp;#048;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#040;&amp;#110;&amp;#032;&amp;#094;&amp;#094;&amp;#094;&amp;#032;&amp;#098;&amp;#041;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#110;&amp;#013;&amp;#010;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#048;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;Compiling the &lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt; with GHC 6.12.3 using --make -O2 flags and running the &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; interactively in Visual Studio 2010 on a Dell Precision T5400 running 32-bit Windows Vista with 4Gb of RAM gave the following results for the on-demand versions:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_NMRkpon4Ps0/TSMjgkVhWWI/AAAAAAAAAK8/bFk4AoC03Wo/s1600/BinaryIOPerformance.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 238px;" src="http://1.bp.blogspot.com/_NMRkpon4Ps0/TSMjgkVhWWI/AAAAAAAAAK8/bFk4AoC03Wo/s400/BinaryIOPerformance.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5558325407522052450" /&gt;&lt;/a&gt;&lt;p&gt;The eager &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; failed due to lack of memory on all three files. The eager &lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt; obtained the correct answer on the smallest file, crashed on the middle file and produced corrupted output on the largest file. These problems appear to stem from a signed 32-bit integer overflowing inside the ByteString library, causing it to either crash when apparently-negative ByteString lengths are encountered or to read only part of a file.&lt;/p&gt;&lt;p&gt;Several points of interest:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The variations between the speed of the &lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt; and &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; solutions is less than 5% in each case.&lt;/li&gt;&lt;li&gt;Wrapping the IO in an IEnumerable (seq in &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt;) severely degrades performance.&lt;/li&gt;&lt;li&gt;On 64-bit machines, memory mapping have different trade-offs.&lt;/li&gt;&lt;li&gt;&lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt;'s ByteString library includes some special functions (e.g. count) that use optimized kernels written in C and assembler to manipulate large quantities of data more efficiently than is currently possible from &lt;a href="http://haskell-news.blogspot.com"&gt;Haskell&lt;/a&gt; or &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;For more information on high-performance &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt;, read &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;Visual F# 2010 for Technical Computing&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-4190817419125695600?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/4190817419125695600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=4190817419125695600' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4190817419125695600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4190817419125695600'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/01/io-throughput-haskell-vs-f.html' title='IO throughput: Haskell vs F#'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_NMRkpon4Ps0/TSMjgkVhWWI/AAAAAAAAAK8/bFk4AoC03Wo/s72-c/BinaryIOPerformance.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-8222579697971352138</id><published>2011-01-01T16:14:00.000-08:00</published><updated>2011-01-01T16:26:13.809-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='purely functional data structure'/><title type='text'>The benefits of purely functional data structures</title><content type='html'>&lt;p&gt;Purely functional data structures have the following advantages:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Persistence:&lt;/b&gt; old versions can be reused safe in the knowledge that they cannot have been changed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Sharing:&lt;/b&gt; many versions of a data structure can be kept simultaneously with relatively modest memory requirements.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Thread safety:&lt;/b&gt; any mutation is hidden inside lazy thunks (if any) and, therefore, thread safety is handled by the language implementation.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Simplicity:&lt;/b&gt; not having to keep track of state changes often makes purely functional data structures simpler to use, particularly in the context of concurrency.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Incrementality:&lt;/b&gt; purely functional data structures are composed of many tiny parts, making them ideal for incremental garbage collection, leading to lower latencies.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Purely functional data structures also have the potential to be beneficial in the context of parallel programming for multicores. However, efficient multicore parallelism requires predictable locality in order to leverage caches and avoid getting bottlenecked on access to shared caches and main memory and purely functional data structures have, at best, unknown characteristics in this regard. Consequently, many programs that use purely functional data structures do not scale well when parallelized on a multicore because they spend all of their time in cache misses, contending for shared memory pathways.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-8222579697971352138?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/8222579697971352138/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=8222579697971352138' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8222579697971352138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8222579697971352138'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/01/benefits-of-purely-functional-data.html' title='The benefits of purely functional data structures'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-4123532808044156084</id><published>2011-01-01T08:03:00.000-08:00</published><updated>2011-01-02T14:17:38.757-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='reference counting'/><category scheme='http://www.blogger.com/atom/ns#' term='shared_ptr'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><title type='text'>Boost's shared_ptr up to 10× slower than OCaml's garbage collection</title><content type='html'>&lt;p&gt;Our &lt;a href="http://flyingfrogblog.blogspot.com/2010/12/why-gc-when-you-have-reference-counted.html"&gt;recent post&lt;/a&gt; about the merits of accurate garbage collection over reference counting prompted Tezka to ask for measurements demonstrating the performance differences between an accurate GC and the reference counted shared_ptr smart pointers provided by the Boost C++ library.&lt;/p&gt;&lt;p&gt;The &lt;a href="http://flyingfrogblog.blogspot.com/2010/12/towards-mark-region-gc-for-hlvm.html"&gt;benchmarks&lt;/a&gt; we have been using to prototype allocators for our HLVM project provide the perfect setting for such an experiment. We already have C++ code that solves the &lt;i&gt;n&lt;/i&gt;-queens problem using logic programming with a variety of different allocation strategies. Adding another version of our benchmark using Boost's shared_ptr gave the following remarkable results:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_NMRkpon4Ps0/TR9TZQDFHoI/AAAAAAAAAK0/7dEkUaqWIhI/s1600/nQueensAllocatorPerformance.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 295px;" src="http://4.bp.blogspot.com/_NMRkpon4Ps0/TR9TZQDFHoI/AAAAAAAAAK0/7dEkUaqWIhI/s400/nQueensAllocatorPerformance.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5557252158468202114" /&gt;&lt;/a&gt;&lt;p&gt;These new results highlight just how slow reference counting can be. The C++ code using Boost's reference counted smart pointers is running up to 10× slower than OCaml!&lt;/p&gt;&lt;p&gt;Note also the new "stack" section that is the first C++ to beat OCaml, albeit cheating by exploiting the fact that this implementation of this benchmark always happens to allocate and free in FIFO order. So this approach is problem-specific and cannot be used as a general-purpose allocator. However, it is worth noting that the only allocation strategy to beat C++ also (like OCaml's nursery) exploits the ability to collect many freed values in constant time by resetting the stack pointer rather than using repeated pops. Therefore, the only allocation strategies likely to approach OCaml's performance on these kinds of problems are those that exploit sparsity. For example, by manipulating free lists in run-length encoded form.&lt;/p&gt;&lt;p&gt;We have yet to find a general-purpose allocation strategy that can match the performance of OCaml's generational garbage collector for these kinds of applications but we can make two interesting observations from these new results:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Reference counting is the only difference between the "free" results (using malloc and free in FIFO order) and these new "shared_ptr" results, so around 80% of the time is spent handling reference counts, far more than is spent in actual allocation and deallocation!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;HLVM currently performs poorly on this benchmark because around &lt;a href="http://flyingfrogblog.blogspot.com/2009/03/current-shadow-stack-overheads-in-hlvm.html"&gt;70% of its time is spent maintaining the shadow stack&lt;/a&gt;, a comparable overhead to the use of reference counting (but one that handles the collection of cycles correctly).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Finally, we should note that our "region 12" results are also new and note that they are significantly worse than the previous "region" results. The difference is that the previous results allocated and deallocated in FIFO order explicitly in the inner loops of the benchmark whereas these new results are a more accurate reflection of the allocation and deallocate patterns that the current version of HLVM generates, specifically the inner loops only maintain the mark bits and deallocation is now performed by sweeps triggered by sufficient allocation. Sweeping results in much worse performance (from 20% slower than OCaml to 2× slower than OCaml). We have invented two ways to attack this problem. Firstly, the thread-local current region could be swept locally, either using a remembered set or just back to the previous write barrier. Secondly, runs of consecutively-allocated unreachable values are likely to appear near the end of the allocated list, so sparse free lists will hopefully accelerate the collection of contiguous sequences of unreachable values.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-4123532808044156084?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/4123532808044156084/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=4123532808044156084' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4123532808044156084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4123532808044156084'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2011/01/boosts-sharedptr-up-to-10-slower-than.html' title='Boost&apos;s shared_ptr up to 10&amp;#215; slower than OCaml&apos;s garbage collection'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_NMRkpon4Ps0/TR9TZQDFHoI/AAAAAAAAAK0/7dEkUaqWIhI/s72-c/nQueensAllocatorPerformance.png' height='72' width='72'/><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-9154642027246313512</id><published>2010-12-29T15:44:00.000-08:00</published><updated>2010-12-29T16:02:32.237-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='template haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='polymorphic variants'/><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='clos'/><category scheme='http://www.blogger.com/atom/ns#' term='type class'/><category scheme='http://www.blogger.com/atom/ns#' term='higher-order module'/><category scheme='http://www.blogger.com/atom/ns#' term='standard ml'/><category scheme='http://www.blogger.com/atom/ns#' term='macro'/><category scheme='http://www.blogger.com/atom/ns#' term='data parallel haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='object oriented programming'/><category scheme='http://www.blogger.com/atom/ns#' term='extensibility'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Extensibility in functional programming languages</title><content type='html'>&lt;p&gt;Most software developers are now familiar with inheritance and virtual methods as common techniques for extensibility from the object oriented paradigm. When faced with functional programming for the first time, these developers often ask how to write extensible code in this alien paradigm.&lt;/p&gt;&lt;p&gt;The functional paradigm actually only provides a single form of extensibility: higher-order functions. These allow you to factor out "inner" functions. For example, code that often appears with the same first and last code blocks:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&lt;span class="Apple-style-span"&gt;let f x =&lt;br /&gt; first x&lt;br /&gt; stuff1 x&lt;br /&gt; last x&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="Apple-style-span"&gt;let g x =&lt;br /&gt; first x&lt;br /&gt; stuff2 x&lt;br /&gt; last x&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;can be factored into a general higher order function that is reused from the specific cases:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;let hof stuff x =&lt;br /&gt; first x&lt;br /&gt; stuff x&lt;br /&gt; last x&lt;/p&gt;&lt;p&gt;let f = hof stuff1 x&lt;/p&gt;&lt;p&gt;let g = hof stuff2 x&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;Applying this aggressively leads to design patterns such as &lt;a href="http://fsharpnews.blogspot.com/2007/12/parser-combinators.html"&gt;parser combinators&lt;/a&gt; and is a very powerful and lightweight technique for making code extensible. However, it does not make data types extensible.&lt;/p&gt;&lt;p&gt;Consequently, functional programming languages almost always include language features to help with extensibility:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Common Lisp has the Common Lisp Object System (CLOS) and a macro system.&lt;/li&gt;&lt;li&gt;Standard ML has parametric polymorphism and a higher-order module system.&lt;/li&gt;&lt;li&gt;OCaml added polymorphic variants, objects, optional arguments and the Camlp4 macro system.&lt;/li&gt;&lt;li&gt;Haskell has parametric polymorphism and type classes, and Template Haskell adds macros.&lt;/li&gt;&lt;li&gt;Scala has Java-style OOP with some added features.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Read Chris Okasaki's excellent monograph &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.64.3080&amp;amp;rep=rep1&amp;amp;type=pdf"&gt;Purely functional data structures&lt;/a&gt; for some great examples using higher-order modules in Standard ML and type classes in Haskell. Read &lt;a href="http://www.math.nagoya-u.ac.jp/~garrigue/papers/fose2000.html"&gt;Code reuse through polymorphic variants&lt;/a&gt; by Jacques Garrigue for a description of how that language feature can be used to attack the expression problem. However, these solutions are quite rare in the wild and, in particular, you can get a long way without them (e.g. in &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;Historically, this diversity appeared because most functional programming languages were research projects and, consequently, they existed to add novel features. Therefore, we now have a wide variety of disparate forms of extensibility in today's functional programming languages.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; is a different beast compared to its predecessors like OCaml and Haskell because its design requirements were seamless interoperability with the rest of .NET (which imposes .NET-style OOP) and pragmatism. Consequently, &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; keeps the ML core with parametric polymorphism and adds .NET's object system. So you can benefit from the easy extensibility offered by generic higher-order functions and conventional OOP but not from any of the more esoteric features like higher-order modules, type classes and macros.&lt;/p&gt;&lt;p&gt;The only form of extensibility &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; has pioneered is &lt;a href="http://fsharpnews.blogspot.com/2010/12/parsing-mathematical-expressions-using.html"&gt;active patterns&lt;/a&gt;. These allow you to separate code that destructures via pattern matching from the concrete data representation. This is an important way to decouple code from data and, therefore, make it more reusable.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-9154642027246313512?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/9154642027246313512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=9154642027246313512' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/9154642027246313512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/9154642027246313512'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/12/extensibility-in-functional-programming.html' title='Extensibility in functional programming languages'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-3435914959530896523</id><published>2010-12-29T15:10:00.000-08:00</published><updated>2010-12-29T15:41:28.688-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><title type='text'>Distinctive traits of functional programming languages</title><content type='html'>&lt;p&gt;The landscape of functional programming languages is remarkably diverse, with most of the major families having quite distinctive traits and dialects that bring their own quirks. Here are some of the major categorizations:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Evaluation strategy&lt;/b&gt;: non-strict (Miranda, Haskell) vs strict evaluation.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Type system&lt;/b&gt;: static (Standard ML, OCaml, F#, Haskell, Scala, C# 3) vs dynamic (Scheme, Lisp, Clojure, Erlang) typing and untyped (Mathematica).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Kind of static typing&lt;/b&gt;: structural (OCaml) vs nominal (F#, Haskell, Scala, C# 3) static typing.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Type inference&lt;/b&gt;: Damas-Milner (Standard ML, OCaml, F#, Haskell) vs "local" inference (Scala, C# 3).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Destructuring&lt;/b&gt;: pattern matching (Standard ML, OCaml, F#, Haskell, Erlang, Mathematica) vs manual deconstruction (Scheme, Lisp, C#).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Extensibility of algebraic types&lt;/b&gt;: always closed (Standard ML, Haskell) vs optionally closed (OCaml).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Pattern matching&lt;/b&gt;: linear (Standard ML, OCaml, Haskell) vs unbounded (F#, Mathematica).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Run-time code generation&lt;/b&gt;: meta-circular evaluator (Scheme, Lisp, Clojure) vs heterogeneous code generation (F# → CIL) vs nothing (Standard ML, OCaml, Haskell).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Macros&lt;/b&gt;: unhygenic macros (Common Lisp, OCaml, Template Haskell, Mathematica) vs hygenic macros (Scheme) vs no macros (Standard ML, F#).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Standardization&lt;/b&gt;: standardized (Standard ML, Haskell 98, Common Lisp, Scheme) vs proprietary (OCaml, F#, GHC Haskell, Erlang, Mathematica).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-3435914959530896523?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/3435914959530896523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=3435914959530896523' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3435914959530896523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3435914959530896523'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/12/distinctive-traits-of-functional.html' title='Distinctive traits of functional programming languages'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-6780086337051464208</id><published>2010-12-29T14:07:00.001-08:00</published><updated>2010-12-29T15:09:57.200-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='reference counting'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Why GC when you have reference counted smart pointers?</title><content type='html'>&lt;p&gt;Reference counted smart pointers are a simple form of garbage collection usable from the C++ programming language. A &lt;a href="http://programmers.stackexchange.com/questions/30254/why-garbage-collection-if-smart-pointers-are-there/"&gt;recent question&lt;/a&gt; on Stack Exchange asks why anyone would want anything more when reference counted smart pointers are already available.&lt;/p&gt;&lt;p&gt;Other forms of garbage collection (most notably tracing GCs) have several advantages over reference counting:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Accuracy:&lt;/b&gt; Reference counting alone leaks cycles so reference counted smart pointers will leak memory in general unless other techniques are added to catch cycles. Once those techniques are added, reference counting's benefit of simplicity has vanished.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Throughput:&lt;/b&gt; Smart pointers are one of the least efficient forms of garbage collection, particularly in the context of multi-threaded applications when reference counts are bumped atomically. There are advanced reference counting techniques designed to alleviate this but tracing GCs are still the algorithm of choice in production environments.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Latency:&lt;/b&gt; Typical smart pointer implementations allow destructors to avalanche, resulting in unbounded pause times. Other forms of garbage collection are much more incremental and can even be real time, e.g. Baker's treadmill.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Many of the answers given perpetuate myths about garbage collection. There is a myth that scope-based reference counting guarantees that values are collected as soon as possible. In fact, tracing collectors can and do collect values before the end of their lexical scope if the value becomes unreachable sooner and a GC occurs. Another myth is that garbage collected languages cannot release resources deterministically. In fact, this is done in exactly the same way as in unmanaged languages. Finally, there is a myth that manual memory management minimizes latency. In fact, manual memory management often has poorer worst-case latency characteristics than garbage collection (this problem originally drove us from C++ to OCaml!) and optimizing latency in an unmanaged language is seriously hard work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-6780086337051464208?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/6780086337051464208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=6780086337051464208' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6780086337051464208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6780086337051464208'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/12/why-gc-when-you-have-reference-counted.html' title='Why GC when you have reference counted smart pointers?'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-2889246965071481659</id><published>2010-12-28T08:10:00.000-08:00</published><updated>2010-12-28T14:38:52.187-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mark region'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Towards a mark-region GC for HLVM</title><content type='html'>&lt;p&gt;Our &lt;a href="http://flyingfrogblog.blogspot.com/2010/12/when-generational-gc-goes-bad.html"&gt;previous article&lt;/a&gt; highlighted the advantages of the recent mark-region GC design and hinted at HLVM adopting this design. We just completed some preliminary tests using a prototype written in C++ to measure the performance of different allocation strategies. Our results are as follows with times normalized by the time an equivalent OCaml program takes (so 1.0 means as fast as OCaml):&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_NMRkpon4Ps0/TRoM5L8NipI/AAAAAAAAAKU/dF4IDSwDNk8/s1600/nQueensAllocatorPerformance.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 212px;" src="http://2.bp.blogspot.com/_NMRkpon4Ps0/TRoM5L8NipI/AAAAAAAAAKU/dF4IDSwDNk8/s400/nQueensAllocatorPerformance.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5555767266912340626" /&gt;&lt;/a&gt;&lt;p&gt;The four columns in each section give the times relative to OCaml for solving the 8-, 9-, 10- and 11-queens problems.&lt;/p&gt;&lt;p&gt;The "Boehm" section refers to the conservative Boehm GC which is 40-70% slower than OCaml on this benchmark. The "malloc" section refers to allocating using the malloc function from glibc without ever freeing and is 2.2-3.1× slower than OCaml. The "free" section refers to allocating with malloc and freeing (manually) and is 1.9-2.3× slower than OCaml. The "bump" section refers to a naive bump allocator that never recycles memory and is 1.4-1.7× slower than OCaml. Finally, the "region" section refers to our prototype region-based algorithm, which is just 4-20% slower than OCaml on this benchmark!&lt;/p&gt;&lt;p&gt;This benchmark is a classic logic programming problem that allocates large numbers of short-lived values. This is a best-case benchmark for OCaml and a worst-case benchmark for the current HLVM. OCaml's generational garbage collector with its fast bump allocator and constant-time recycling of dead values from the nursery generation does &lt;i&gt;extremely&lt;/i&gt; well on this benchmark: we have been unable to beat its performance from C/C++.&lt;/p&gt;&lt;p&gt;The Boehm garbage collector is another interesting point of comparison because it has been the subject of intense optimization for many years.&lt;/p&gt;&lt;p&gt;These new results are very enlightening. Recycling memory by calling free is significantly faster than leaking memory by only ever calling malloc. Specifically, leaking is around 3× slower than OCaml and proper manual memory management using malloc and free is around 2× slower than OCaml. Moreover, the performance of the Boehm GC is very similar to manual memory management but still 2× slower than OCaml.&lt;/p&gt;&lt;p&gt;Bump allocating from a huge preallocated pool without ever freeing is surprisingly slow: around 1.5× slower than OCaml. This early result was disappointing but it turned out that our new region allocator is very fast indeed. This is extremely encouraging because it means that a non-moving mark-region collector for HLVM might be able to offer the best of both worlds: the speed of C/C++/Fortran for imperative code using mutable data structures and the speed of OCaml/Haskell for functional code using immutable data structures.&lt;/p&gt;&lt;p&gt;Our prototype region allocator allocates aligned regions using the glibc &lt;a href="http://www.delorie.com/gnu/docs/glibc/libc_31.html"&gt;memalign&lt;/a&gt; function. This allows a pointer to the start of the region to be obtained from any pointer inside the region using bitwise operations. Each region begins with a C++ vector that holds the &lt;i&gt;free list&lt;/i&gt;, the list of pointers inside the region that are not currently allocated. The remainder of the region is a pool of fixed-size blocks that can be allocated and deallocated. To allocate, the last element is popped off the free list. To free, the free list associated with the pointer is obtained using bitwise operations and the pointer is pushed onto the back of the free list. In the prototype, if the allocator finds the current region to be full then it stores it in a global collection of regions and allocates a new local region. In a production version, the allocator would recycle one of the non-full regions from the global collection of regions rather than allocating a new region each time.&lt;/p&gt;&lt;p&gt;How big should a region be? The results shown above were obtained using 1MB regions, large enough that they were never filled and a new region was never needed. However, reducing the region size to 1kB causes the prototype to create 8,295 regions on the 11-queens problem but the program is only 5% slower and total memory consumption is around 99% lower than simply leaking, so memory is being recycled effectively.&lt;/p&gt;&lt;p&gt;Measuring the absolute performance of the 10-queens solver as a function of the region size gives the following results:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_NMRkpon4Ps0/TRovzaw9JGI/AAAAAAAAAKk/_BL4AS5Tcl4/s1600/nQueensAllocatorEfficiency.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 238px;" src="http://3.bp.blogspot.com/_NMRkpon4Ps0/TRovzaw9JGI/AAAAAAAAAKk/_BL4AS5Tcl4/s400/nQueensAllocatorEfficiency.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5555805650719417442" /&gt;&lt;/a&gt;&lt;p&gt;The smallest possible region size of 16 bytes allows a single allocation per region and makes the whole program run 7.6× slower. Increasing the region size improves the efficiency of the region allocator (except for an anomaly between 128 and 256 byte regions that is probably due to benchmark-specific allocation patterns). With 1,024-byte regions, performance is within a few percent of optimal for this benchmark. One might have expected to see significant performance gains from larger regions up to the size of the 6Mb L2 cache on this machine but the tiny working set required by this benchmark eliminated any performance difference beyond 1kB regions.&lt;/p&gt;&lt;p&gt;The following graph shows the number of regions allocated for different region sizes on the 10-queens benchmark:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_NMRkpon4Ps0/TRo0Mfzp4LI/AAAAAAAAAKs/P3KviqjhGcM/s1600/nQueensAllocatorRegions.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 238px;" src="http://3.bp.blogspot.com/_NMRkpon4Ps0/TRo0Mfzp4LI/AAAAAAAAAKs/P3KviqjhGcM/s400/nQueensAllocatorRegions.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5555810479616155826" /&gt;&lt;/a&gt;&lt;p&gt;Smaller regions means a larger number of regions are required, up to around ten million for 16-byte regions. The relationship here reflects the previous region size vs performance relationship because the most of the time is spent administering regions when they are small. The initial sharp drop-off occurs because allowing regions to contain just a few more values significantly increases their ability to recycle space. With 1kB regions, only 874 regions are created to solve this problem.&lt;/p&gt;&lt;p&gt;The product of the region size and number of regions used quantifies the total space allocated for regions using glibc. Doubling the region size from 64 bytes to 128 bytes reduces the total memory allocated by 33% and doubling the region size from 2kB to 4kB reduces the total memory allocated by 99%. Perhaps the accelerated efficiency is due to the generational hypothesis that predicts inverse hyper-exponential decay of the probability of death as a function of age.&lt;/p&gt;&lt;p&gt;In HLVM, a thread-safe allocator will try to use the thread-local region and resort to synchronization only when obtaining the current region is full whereupon an existing non-full region will be reused or a new empty region will be created. The deallocator must potentially access any region but, with HLVM's current design, it is only invoked from a single thread during the stop-the-world phase so it can be &lt;i&gt;thread unsafe&lt;/i&gt;. This has two benefits over the current technique:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Single-threaded allocation and deallocation should be almost twice as fast as they are today.&lt;/li&gt;&lt;li&gt;Multi-threaded allocation should scale linearly with the number of cores whereas HLVM currently sees performance degradation from concurrent allocations.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;However, our &lt;a href="http://flyingfrogblog.blogspot.com/2009/03/current-shadow-stack-overheads-in-hlvm.html"&gt;previous results&lt;/a&gt; indicated that HLVM's currently-dismal performance on this benchmark is actually due to the shadow stack and not to allocation. We anticipate that efficient concurrent allocation will be the next bottleneck after the performance of the shadow stack is addressed so this is still valuable work.&lt;/p&gt;&lt;p&gt;Two pieces of related work remain to be done:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Mimic the effects of HLVM's current GC more accurately by deallocating in chunks.&lt;/li&gt;&lt;li&gt;Extend the prototype to reuse existing non-full regions before allocating a new empty region.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-2889246965071481659?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/2889246965071481659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=2889246965071481659' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2889246965071481659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2889246965071481659'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/12/towards-mark-region-gc-for-hlvm.html' title='Towards a mark-region GC for HLVM'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_NMRkpon4Ps0/TRoM5L8NipI/AAAAAAAAAKU/dF4IDSwDNk8/s72-c/nQueensAllocatorPerformance.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-2019211030298684197</id><published>2010-12-23T17:05:00.000-08:00</published><updated>2010-12-24T06:04:48.453-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mark region'/><category scheme='http://www.blogger.com/atom/ns#' term='generational garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>When generational GC goes bad</title><content type='html'>&lt;p&gt;For many years, generational collection was the defacto-standard GC architecture. Based upon the observation that the distribution of value lifetimes is heavily skewed towards short lifetimes (most values die young), generational garbage collectors allocate into a nursery generation and survivors are copied out into an old generation.&lt;/p&gt;&lt;p&gt;Many practical language implementations use generational garbage collection including OCaml, GHC and .NET. Generational collection works well when the generational hypothesis holds but struggles when values survive the nursery only to become unreachable soon afterwards. This corresponds to common allocation patterns such as cycling values through mutable queues or caches and filling hash tables.&lt;/p&gt;&lt;p&gt;Imagine repeatedly enqueuing and dequeuing values on a queue. The lifetimes of the values are proportional to the length of the queue. Thus, this provides a simple way to quantify the performance overhead of generational garbage collection. If boxed values are enqueued and dequeued on OCaml's built-in mutable Queue data structure then the time taken per element jumps by around a factor of 2-3.5 when the elements reachable from the queue exceed the size of the nursery and, thus, most survive to the old generation rather than being collected efficiently in the young generation. Specifically, the time taken to enqueue and dequeue 32-bit ints on this 2.1GHz 2352 Opteron jumps from 0.33μs to 0.68-1.13μs. Where is this time being wasted?&lt;/p&gt;&lt;p&gt;When a boxed value (such as a 32-bit integer) is allocated in OCaml, it is augmented with a 1-word header and another for the forwarding pointer and that whole block is bump allocated from the nursery. When that value is written into the Queue in the old generation, a write barrier is incurred which stores a copy of the reference in the remembered set. When the nursery is filled, a minor collection is performed that traces from the global roots and remembered set throughout the reachable values in the nursery. These values are then copied into the old generation, their forwarding pointers are set and all locally-held references to them are updated via the forwarding pointers to point into their copies in the old generation. The nursery is then swept by resetting the bump allocator to the start of the nursery.&lt;/p&gt;&lt;p&gt;Suffice to say, this is a lot of overhead when the values allocated into the nursery do not die quickly enough. In that case, all of this effort is a complete waste of time and we would have been better off allocating directly into the old generation in the first place. What can be done to address this problem?&lt;/p&gt;&lt;p&gt;Fortunately, McKinley et al. made a breakthrough in GC design in recent years with their invention of a new class of GC algorithms known as mark-region GCs. It all began with their invention of the &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.138.8778&amp;amp;rep=rep1&amp;amp;type=pdf"&gt;Beltway&lt;/a&gt; GC in 2002, a generalization of several existing GC designs, and culminated in their &lt;a href="http://cs.anu.edu.au/techreports/2007/TR-CS-07-04.pdf"&gt;Immix&lt;/a&gt; GC in 2007. In effect, this GC design allows a nursery full of reachable values to be migrated to the old heap implicitly without any copying and a new nursery is allocated to replace it. The old generation is then effectively a collection of surviving nurseries. The precise placement policy is more complicated because it is possible to reuse old nurseries in order to avoid gross fragmentation but the basic concept is simple enough.&lt;/p&gt;&lt;p&gt;A &lt;a href="http://socghop.appspot.com/gsoc/student_project/show/google/gsoc2010/haskell/t127230760695"&gt;Google Summer of Code project&lt;/a&gt; had an Immix variant implemented for the Glasgow Haskell Compiler. They found the results to be underwhelming but that is not so surprising given that this GC design should be most effective when filling mutable data structures such as queues, caches, hash sets and hash tables. We believe that a simple mark-region variant should be able to dramatically improve &lt;a href="http://www.ffconsultancy.com/ocaml/hlvm/"&gt;HLVM&lt;/a&gt;'s performance on parallel functional code without degrading the performance of imperative code as generational garbage collectors like OCaml's do.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-2019211030298684197?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/2019211030298684197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=2019211030298684197' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2019211030298684197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2019211030298684197'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/12/when-generational-gc-goes-bad.html' title='When generational GC goes bad'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-5858172736240486109</id><published>2010-12-15T10:56:00.000-08:00</published><updated>2010-12-15T14:16:27.704-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='industrial haskell group'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><title type='text'>Getting paid to remove features</title><content type='html'>&lt;p&gt;Although the &lt;a href="http://industry.haskell.org/"&gt;Industrial Haskell Group&lt;/a&gt; has yet to garner its first industrial member since its inception almost two years ago, they have managed the impressive feat of getting paid to remove a feature from Haskell. Specifically, to make it easier to build programs written in Haskell that do not rely upon the GNU Multiprecision library for arbitrary-precision arithmetic (bignums).&lt;/p&gt;&lt;p&gt;We made this interesting observation when considering adding bignums using GMP as a primitive type for &lt;a href="http://www.ffconsultancy.com/ocaml/hlvm/"&gt;HLVM&lt;/a&gt;. Apparently, having bignums in the language is not very useful beyond irrelevant microbenchmarks like &lt;a href="http://shootout.alioth.debian.org/u64q/benchmark.php?test=pidigits&amp;amp;lang=gcc"&gt;computing the digits of &lt;span class="Apple-style-span"&gt;π&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The slides &lt;a href="http://www.well-typed.com/blog/aux/files/ihg-talk.pdf"&gt;here&lt;/a&gt; also criticize the &lt;a href="http://caml.inria.fr/consortium/"&gt;CAML Consortium&lt;/a&gt; (which has garnered 11 members) for charging too little and states that the IHG aimed to garner five members each paying £12k per annum. Why has this target not yet been reached? Our guess is insufficient sales and marketing directed at decision makers in industry who could benefit from using Haskell. As an aside, we believe this same mistake is why the founders of Stack Overflow found it so difficult to monetize despite having millions of non-paying users. In contrast, Rich Hickey managed to garner funding from a whopping &lt;a href="http://clojure.org/funding"&gt;427 people and several companies&lt;/a&gt; for his own language, Clojure.&lt;/p&gt;&lt;p&gt;Regardless, the fact that they are trying to build a business around the development of Haskell itself is admirable and should at least prompt more professionals to take a look at what is on offer.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-5858172736240486109?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/5858172736240486109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=5858172736240486109' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5858172736240486109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5858172736240486109'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/12/getting-paid-to-remove-features.html' title='Getting paid to remove features'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-2063123556582184682</id><published>2010-12-05T07:46:00.000-08:00</published><updated>2010-12-05T08:07:27.320-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='parallel'/><category scheme='http://www.blogger.com/atom/ns#' term='Texas Multicore Technologies'/><title type='text'>Texas Multicore Technologies on Haskell</title><content type='html'>&lt;p&gt;US-based startup Texas Multicore Technologies have &lt;a href="http://www.texasmulticoretechnologies.com/technology/example/"&gt;published some of the results&lt;/a&gt; they obtained using Haskell for parallel programming. Their results mirror &lt;a href="http://flyingfrogblog.blogspot.com/2010/01/naive-parallelism-with-hlvm.html"&gt;our own&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.texasmulticoretechnologies.com/images/matrix_multiply_performance.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 566px; height: 258px;" src="http://www.texasmulticoretechnologies.com/images/matrix_multiply_performance.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;p&gt;Thanks to &lt;a href="http://www.cse.unsw.edu.au/~chak/"&gt;Manuel Chakravarty&lt;/a&gt; of the University of New South Wales for &lt;a href="http://twitter.com/#!/TacticalGrace/status/5085812169375744"&gt;drawing this to our attention&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-2063123556582184682?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/2063123556582184682/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=2063123556582184682' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2063123556582184682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2063123556582184682'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/12/texas-multicore-technologies-on-haskell.html' title='Texas Multicore Technologies on Haskell'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-5382123616910031215</id><published>2010-11-06T16:15:00.000-07:00</published><updated>2010-11-06T17:37:34.424-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='boehm'/><category scheme='http://www.blogger.com/atom/ns#' term='mono'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Mono 2.8: a step closer to a reliable foundation</title><content type='html'>&lt;p&gt;We &lt;a href="http://flyingfrogblog.blogspot.com/2010/07/mono-24-still-leaking-like-sieve.html"&gt;previously complained&lt;/a&gt; about the use of Boehm's conservative garbage collector in earlier versions of Mono because it is fundamentally flawed and prone to causing unpredictable memory leaks that result in applications dying with out-of-memory errors when there is plenty of garbage left to be reclaimed. Specifically, we gave a simple 9-line example program that fills and forgets ten hash tables that ran out of memory when run on Mono 2.4. What happens when this program is run on Mono 2.8 using the new SGen garbage collector?&lt;/p&gt;&lt;p&gt;Running the test with Mono 2.8 using the default Boehm GC often reproduces the same leak that we saw before, as expected. Repeating our previous test using the new SGen garbage collector we find that the program does not die after four iterations with an out-of-memory error but gets as far as eight of the intended ten iterations before dying with a segmentation fault:&lt;/p&gt;&lt;p&gt;&lt;pre&gt;&amp;#036;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#084;&amp;#097;&amp;#105;&amp;#108;&amp;#067;&amp;#097;&amp;#108;&amp;#108;&amp;#046;&amp;#101;&amp;#120;&amp;#101;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#052;&amp;#048;&amp;#053;&amp;#049;&amp;#049;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#052;&amp;#049;&amp;#050;&amp;#055;&amp;#051;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#050;&amp;#048;&amp;#052;&amp;#054;&amp;#052;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#057;&amp;#054;&amp;#053;&amp;#051;&amp;#052;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#049;&amp;#052;&amp;#057;&amp;#052;&amp;#052;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#049;&amp;#048;&amp;#049;&amp;#049;&amp;#052;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#049;&amp;#052;&amp;#049;&amp;#056;&amp;#055;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#050;&amp;#055;&amp;#049;&amp;#050;&amp;#051;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#083;&amp;#116;&amp;#097;&amp;#099;&amp;#107;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#101;&amp;#058;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#040;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#032;&amp;#109;&amp;#097;&amp;#110;&amp;#097;&amp;#103;&amp;#101;&amp;#100;&amp;#045;&amp;#116;&amp;#111;&amp;#045;&amp;#110;&amp;#097;&amp;#116;&amp;#105;&amp;#118;&amp;#101;&amp;#041;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#046;&amp;#095;&amp;#095;&amp;#105;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#095;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#095;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#103;&amp;#099;&amp;#095;&amp;#097;&amp;#108;&amp;#108;&amp;#111;&amp;#099;&amp;#095;&amp;#118;&amp;#101;&amp;#099;&amp;#116;&amp;#111;&amp;#114;&amp;#032;&amp;#040;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#041;&amp;#032;&amp;#060;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#051;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#040;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#032;&amp;#109;&amp;#097;&amp;#110;&amp;#097;&amp;#103;&amp;#101;&amp;#100;&amp;#045;&amp;#116;&amp;#111;&amp;#045;&amp;#110;&amp;#097;&amp;#116;&amp;#105;&amp;#118;&amp;#101;&amp;#041;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#046;&amp;#095;&amp;#095;&amp;#105;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#095;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#095;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#103;&amp;#099;&amp;#095;&amp;#097;&amp;#108;&amp;#108;&amp;#111;&amp;#099;&amp;#095;&amp;#118;&amp;#101;&amp;#099;&amp;#116;&amp;#111;&amp;#114;&amp;#032;&amp;#040;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#041;&amp;#032;&amp;#060;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#051;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#040;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#032;&amp;#097;&amp;#108;&amp;#108;&amp;#111;&amp;#099;&amp;#041;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#046;&amp;#065;&amp;#108;&amp;#108;&amp;#111;&amp;#099;&amp;#086;&amp;#101;&amp;#099;&amp;#116;&amp;#111;&amp;#114;&amp;#032;&amp;#040;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#041;&amp;#032;&amp;#060;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#097;&amp;#099;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#067;&amp;#111;&amp;#108;&amp;#108;&amp;#101;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#046;&amp;#071;&amp;#101;&amp;#110;&amp;#101;&amp;#114;&amp;#105;&amp;#099;&amp;#046;&amp;#068;&amp;#105;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#097;&amp;#114;&amp;#121;&amp;#096;&amp;#050;&amp;#060;&amp;#100;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#044;&amp;#032;&amp;#100;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#062;&amp;#046;&amp;#082;&amp;#101;&amp;#115;&amp;#105;&amp;#122;&amp;#101;&amp;#032;&amp;#040;&amp;#041;&amp;#032;&amp;#060;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#049;&amp;#098;&amp;#099;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#067;&amp;#111;&amp;#108;&amp;#108;&amp;#101;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#046;&amp;#071;&amp;#101;&amp;#110;&amp;#101;&amp;#114;&amp;#105;&amp;#099;&amp;#046;&amp;#068;&amp;#105;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#097;&amp;#114;&amp;#121;&amp;#096;&amp;#050;&amp;#060;&amp;#100;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#044;&amp;#032;&amp;#100;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#062;&amp;#046;&amp;#115;&amp;#101;&amp;#116;&amp;#095;&amp;#073;&amp;#116;&amp;#101;&amp;#109;&amp;#032;&amp;#040;&amp;#100;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#044;&amp;#100;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#041;&amp;#032;&amp;#060;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#049;&amp;#052;&amp;#102;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#060;&amp;#083;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#117;&amp;#112;&amp;#067;&amp;#111;&amp;#100;&amp;#101;&amp;#036;&amp;#084;&amp;#097;&amp;#105;&amp;#108;&amp;#067;&amp;#097;&amp;#108;&amp;#108;&amp;#062;&amp;#046;&amp;#036;&amp;#080;&amp;#114;&amp;#111;&amp;#103;&amp;#114;&amp;#097;&amp;#109;&amp;#046;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#064;&amp;#032;&amp;#040;&amp;#041;&amp;#032;&amp;#060;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#055;&amp;#099;&amp;#062;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#040;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#032;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#045;&amp;#105;&amp;#110;&amp;#118;&amp;#111;&amp;#107;&amp;#101;&amp;#041;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#046;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#095;&amp;#105;&amp;#110;&amp;#118;&amp;#111;&amp;#107;&amp;#101;&amp;#095;&amp;#118;&amp;#111;&amp;#105;&amp;#100;&amp;#032;&amp;#040;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#041;&amp;#032;&amp;#060;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#055;&amp;#100;&amp;#062;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#078;&amp;#097;&amp;#116;&amp;#105;&amp;#118;&amp;#101;&amp;#032;&amp;#115;&amp;#116;&amp;#097;&amp;#099;&amp;#107;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#101;&amp;#058;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#048;&amp;#100;&amp;#101;&amp;#099;&amp;#051;&amp;#052;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#049;&amp;#050;&amp;#098;&amp;#050;&amp;#099;&amp;#098;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#054;&amp;#102;&amp;#051;&amp;#052;&amp;#049;&amp;#048;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#049;&amp;#055;&amp;#052;&amp;#101;&amp;#049;&amp;#055;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#049;&amp;#055;&amp;#053;&amp;#052;&amp;#050;&amp;#056;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#099;&amp;#098;&amp;#048;&amp;#098;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#057;&amp;#055;&amp;#100;&amp;#053;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#099;&amp;#054;&amp;#057;&amp;#053;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#099;&amp;#050;&amp;#097;&amp;#056;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#056;&amp;#100;&amp;#057;&amp;#100;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#056;&amp;#102;&amp;#100;&amp;#054;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#048;&amp;#054;&amp;#053;&amp;#051;&amp;#049;&amp;#056;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#040;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#095;&amp;#105;&amp;#110;&amp;#118;&amp;#111;&amp;#107;&amp;#101;&amp;#043;&amp;#048;&amp;#120;&amp;#052;&amp;#048;&amp;#041;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#049;&amp;#097;&amp;#057;&amp;#097;&amp;#097;&amp;#048;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#040;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#095;&amp;#101;&amp;#120;&amp;#101;&amp;#099;&amp;#095;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#043;&amp;#048;&amp;#120;&amp;#100;&amp;#054;&amp;#041;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#049;&amp;#097;&amp;#100;&amp;#049;&amp;#102;&amp;#054;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#040;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#043;&amp;#048;&amp;#120;&amp;#049;&amp;#097;&amp;#052;&amp;#049;&amp;#041;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#048;&amp;#098;&amp;#098;&amp;#053;&amp;#048;&amp;#049;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#048;&amp;#053;&amp;#098;&amp;#051;&amp;#056;&amp;#056;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#047;&amp;#108;&amp;#105;&amp;#098;&amp;#047;&amp;#116;&amp;#108;&amp;#115;&amp;#047;&amp;#105;&amp;#054;&amp;#056;&amp;#054;&amp;#047;&amp;#099;&amp;#109;&amp;#111;&amp;#118;&amp;#047;&amp;#108;&amp;#105;&amp;#098;&amp;#099;&amp;#046;&amp;#115;&amp;#111;&amp;#046;&amp;#054;&amp;#040;&amp;#095;&amp;#095;&amp;#108;&amp;#105;&amp;#098;&amp;#099;&amp;#095;&amp;#115;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#095;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#043;&amp;#048;&amp;#120;&amp;#101;&amp;#054;&amp;#041;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#052;&amp;#053;&amp;#049;&amp;#098;&amp;#053;&amp;#054;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#056;&amp;#048;&amp;#053;&amp;#098;&amp;#049;&amp;#051;&amp;#049;&amp;#093;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#068;&amp;#101;&amp;#098;&amp;#117;&amp;#103;&amp;#032;&amp;#105;&amp;#110;&amp;#102;&amp;#111;&amp;#032;&amp;#102;&amp;#114;&amp;#111;&amp;#109;&amp;#032;&amp;#103;&amp;#100;&amp;#098;&amp;#058;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#091;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#100;&amp;#101;&amp;#098;&amp;#117;&amp;#103;&amp;#103;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#117;&amp;#115;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#108;&amp;#105;&amp;#098;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#095;&amp;#100;&amp;#098;&amp;#032;&amp;#101;&amp;#110;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#100;&amp;#093;&amp;#013;&amp;#010;&amp;#091;&amp;#078;&amp;#101;&amp;#119;&amp;#032;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#049;&amp;#048;&amp;#051;&amp;#098;&amp;#055;&amp;#048;&amp;#032;&amp;#040;&amp;#076;&amp;#087;&amp;#080;&amp;#032;&amp;#056;&amp;#052;&amp;#048;&amp;#049;&amp;#041;&amp;#093;&amp;#013;&amp;#010;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#054;&amp;#102;&amp;#051;&amp;#052;&amp;#051;&amp;#048;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#095;&amp;#095;&amp;#107;&amp;#101;&amp;#114;&amp;#110;&amp;#101;&amp;#108;&amp;#095;&amp;#118;&amp;#115;&amp;#121;&amp;#115;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#050;&amp;#032;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#049;&amp;#048;&amp;#051;&amp;#098;&amp;#055;&amp;#048;&amp;#032;&amp;#040;&amp;#076;&amp;#087;&amp;#080;&amp;#032;&amp;#056;&amp;#052;&amp;#048;&amp;#049;&amp;#041;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#054;&amp;#102;&amp;#051;&amp;#052;&amp;#051;&amp;#048;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#095;&amp;#095;&amp;#107;&amp;#101;&amp;#114;&amp;#110;&amp;#101;&amp;#108;&amp;#095;&amp;#118;&amp;#115;&amp;#121;&amp;#115;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#042;&amp;#032;&amp;#049;&amp;#032;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#052;&amp;#051;&amp;#057;&amp;#055;&amp;#050;&amp;#048;&amp;#032;&amp;#040;&amp;#076;&amp;#087;&amp;#080;&amp;#032;&amp;#056;&amp;#052;&amp;#048;&amp;#048;&amp;#041;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#054;&amp;#102;&amp;#051;&amp;#052;&amp;#051;&amp;#048;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#095;&amp;#095;&amp;#107;&amp;#101;&amp;#114;&amp;#110;&amp;#101;&amp;#108;&amp;#095;&amp;#118;&amp;#115;&amp;#121;&amp;#115;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#050;&amp;#032;&amp;#040;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#049;&amp;#048;&amp;#051;&amp;#098;&amp;#055;&amp;#048;&amp;#032;&amp;#040;&amp;#076;&amp;#087;&amp;#080;&amp;#032;&amp;#056;&amp;#052;&amp;#048;&amp;#049;&amp;#041;&amp;#041;&amp;#058;&amp;#013;&amp;#010;&amp;#035;&amp;#048;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#054;&amp;#102;&amp;#051;&amp;#052;&amp;#051;&amp;#048;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#095;&amp;#095;&amp;#107;&amp;#101;&amp;#114;&amp;#110;&amp;#101;&amp;#108;&amp;#095;&amp;#118;&amp;#115;&amp;#121;&amp;#115;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#053;&amp;#097;&amp;#057;&amp;#102;&amp;#055;&amp;#053;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#115;&amp;#101;&amp;#109;&amp;#095;&amp;#119;&amp;#097;&amp;#105;&amp;#116;&amp;#064;&amp;#064;&amp;#071;&amp;#076;&amp;#073;&amp;#066;&amp;#067;&amp;#095;&amp;#050;&amp;#046;&amp;#049;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#046;&amp;#046;&amp;#047;&amp;#110;&amp;#112;&amp;#116;&amp;#108;&amp;#047;&amp;#115;&amp;#121;&amp;#115;&amp;#100;&amp;#101;&amp;#112;&amp;#115;&amp;#047;&amp;#117;&amp;#110;&amp;#105;&amp;#120;&amp;#047;&amp;#115;&amp;#121;&amp;#115;&amp;#118;&amp;#047;&amp;#108;&amp;#105;&amp;#110;&amp;#117;&amp;#120;&amp;#047;&amp;#105;&amp;#051;&amp;#056;&amp;#054;&amp;#047;&amp;#105;&amp;#054;&amp;#056;&amp;#054;&amp;#047;&amp;#046;&amp;#046;&amp;#047;&amp;#105;&amp;#052;&amp;#056;&amp;#054;&amp;#047;&amp;#115;&amp;#101;&amp;#109;&amp;#095;&amp;#119;&amp;#097;&amp;#105;&amp;#116;&amp;#046;&amp;#083;&amp;#058;&amp;#056;&amp;#048;&amp;#013;&amp;#010;&amp;#035;&amp;#050;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#050;&amp;#050;&amp;#099;&amp;#055;&amp;#055;&amp;#056;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#115;&amp;#101;&amp;#109;&amp;#095;&amp;#119;&amp;#097;&amp;#105;&amp;#116;&amp;#032;&amp;#040;&amp;#115;&amp;#101;&amp;#109;&amp;#061;&amp;#048;&amp;#120;&amp;#056;&amp;#057;&amp;#099;&amp;#101;&amp;#054;&amp;#052;&amp;#099;&amp;#044;&amp;#032;&amp;#097;&amp;#108;&amp;#101;&amp;#114;&amp;#116;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#061;&amp;#048;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#045;&amp;#115;&amp;#101;&amp;#109;&amp;#097;&amp;#112;&amp;#104;&amp;#111;&amp;#114;&amp;#101;&amp;#046;&amp;#099;&amp;#058;&amp;#049;&amp;#048;&amp;#050;&amp;#013;&amp;#010;&amp;#035;&amp;#051;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#053;&amp;#054;&amp;#048;&amp;#099;&amp;#055;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#097;&amp;#108;&amp;#105;&amp;#122;&amp;#101;&amp;#114;&amp;#095;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#040;&amp;#117;&amp;#110;&amp;#117;&amp;#115;&amp;#101;&amp;#100;&amp;#061;&amp;#048;&amp;#120;&amp;#048;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#103;&amp;#099;&amp;#046;&amp;#099;&amp;#058;&amp;#049;&amp;#048;&amp;#052;&amp;#056;&amp;#013;&amp;#010;&amp;#035;&amp;#052;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#056;&amp;#051;&amp;#048;&amp;#054;&amp;#053;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#115;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#095;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#032;&amp;#040;&amp;#100;&amp;#097;&amp;#116;&amp;#097;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#055;&amp;#099;&amp;#055;&amp;#054;&amp;#048;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#115;&amp;#046;&amp;#099;&amp;#058;&amp;#055;&amp;#052;&amp;#055;&amp;#013;&amp;#010;&amp;#035;&amp;#053;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#050;&amp;#049;&amp;#097;&amp;#055;&amp;#100;&amp;#102;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#095;&amp;#115;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#095;&amp;#114;&amp;#111;&amp;#117;&amp;#116;&amp;#105;&amp;#110;&amp;#101;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#103;&amp;#115;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#054;&amp;#055;&amp;#054;&amp;#050;&amp;#099;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#119;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#115;&amp;#046;&amp;#099;&amp;#058;&amp;#050;&amp;#056;&amp;#053;&amp;#013;&amp;#010;&amp;#035;&amp;#054;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#054;&amp;#100;&amp;#097;&amp;#056;&amp;#098;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#103;&amp;#099;&amp;#095;&amp;#115;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#095;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#103;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#055;&amp;#099;&amp;#056;&amp;#048;&amp;#056;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#045;&amp;#103;&amp;#099;&amp;#046;&amp;#099;&amp;#058;&amp;#053;&amp;#051;&amp;#053;&amp;#048;&amp;#013;&amp;#010;&amp;#035;&amp;#055;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#053;&amp;#097;&amp;#051;&amp;#056;&amp;#048;&amp;#101;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#115;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#095;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#103;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#049;&amp;#048;&amp;#051;&amp;#098;&amp;#055;&amp;#048;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#112;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#095;&amp;#099;&amp;#114;&amp;#101;&amp;#097;&amp;#116;&amp;#101;&amp;#046;&amp;#099;&amp;#058;&amp;#051;&amp;#048;&amp;#048;&amp;#013;&amp;#010;&amp;#035;&amp;#056;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#053;&amp;#048;&amp;#055;&amp;#056;&amp;#100;&amp;#101;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#099;&amp;#108;&amp;#111;&amp;#110;&amp;#101;&amp;#032;&amp;#040;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#046;&amp;#046;&amp;#047;&amp;#115;&amp;#121;&amp;#115;&amp;#100;&amp;#101;&amp;#112;&amp;#115;&amp;#047;&amp;#117;&amp;#110;&amp;#105;&amp;#120;&amp;#047;&amp;#115;&amp;#121;&amp;#115;&amp;#118;&amp;#047;&amp;#108;&amp;#105;&amp;#110;&amp;#117;&amp;#120;&amp;#047;&amp;#105;&amp;#051;&amp;#056;&amp;#054;&amp;#047;&amp;#099;&amp;#108;&amp;#111;&amp;#110;&amp;#101;&amp;#046;&amp;#083;&amp;#058;&amp;#049;&amp;#051;&amp;#048;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#049;&amp;#032;&amp;#040;&amp;#084;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#052;&amp;#051;&amp;#057;&amp;#055;&amp;#050;&amp;#048;&amp;#032;&amp;#040;&amp;#076;&amp;#087;&amp;#080;&amp;#032;&amp;#056;&amp;#052;&amp;#048;&amp;#048;&amp;#041;&amp;#041;&amp;#058;&amp;#013;&amp;#010;&amp;#035;&amp;#048;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#054;&amp;#102;&amp;#051;&amp;#052;&amp;#051;&amp;#048;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#095;&amp;#095;&amp;#107;&amp;#101;&amp;#114;&amp;#110;&amp;#101;&amp;#108;&amp;#095;&amp;#118;&amp;#115;&amp;#121;&amp;#115;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#053;&amp;#097;&amp;#097;&amp;#099;&amp;#056;&amp;#098;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#040;&amp;#041;&amp;#032;&amp;#102;&amp;#114;&amp;#111;&amp;#109;&amp;#032;&amp;#047;&amp;#108;&amp;#105;&amp;#098;&amp;#047;&amp;#116;&amp;#108;&amp;#115;&amp;#047;&amp;#105;&amp;#054;&amp;#056;&amp;#054;&amp;#047;&amp;#099;&amp;#109;&amp;#111;&amp;#118;&amp;#047;&amp;#108;&amp;#105;&amp;#098;&amp;#112;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#046;&amp;#115;&amp;#111;&amp;#046;&amp;#048;&amp;#013;&amp;#010;&amp;#035;&amp;#050;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#048;&amp;#100;&amp;#101;&amp;#100;&amp;#102;&amp;#099;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#040;&amp;#115;&amp;#105;&amp;#103;&amp;#110;&amp;#097;&amp;#108;&amp;#061;&amp;#049;&amp;#049;&amp;#044;&amp;#032;&amp;#099;&amp;#116;&amp;#120;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#102;&amp;#099;&amp;#100;&amp;#048;&amp;#099;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#047;&amp;#117;&amp;#115;&amp;#114;&amp;#047;&amp;#105;&amp;#110;&amp;#099;&amp;#108;&amp;#117;&amp;#100;&amp;#101;&amp;#047;&amp;#098;&amp;#105;&amp;#116;&amp;#115;&amp;#047;&amp;#117;&amp;#110;&amp;#105;&amp;#115;&amp;#116;&amp;#100;&amp;#046;&amp;#104;&amp;#058;&amp;#052;&amp;#053;&amp;#013;&amp;#010;&amp;#035;&amp;#051;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#104;&amp;#097;&amp;#110;&amp;#100;&amp;#108;&amp;#101;&amp;#095;&amp;#110;&amp;#097;&amp;#116;&amp;#105;&amp;#118;&amp;#101;&amp;#095;&amp;#115;&amp;#105;&amp;#103;&amp;#115;&amp;#101;&amp;#103;&amp;#118;&amp;#032;&amp;#040;&amp;#115;&amp;#105;&amp;#103;&amp;#110;&amp;#097;&amp;#108;&amp;#061;&amp;#049;&amp;#049;&amp;#044;&amp;#032;&amp;#099;&amp;#116;&amp;#120;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#102;&amp;#099;&amp;#100;&amp;#048;&amp;#099;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#109;&amp;#105;&amp;#110;&amp;#105;&amp;#045;&amp;#101;&amp;#120;&amp;#099;&amp;#101;&amp;#112;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#046;&amp;#099;&amp;#058;&amp;#049;&amp;#057;&amp;#051;&amp;#053;&amp;#013;&amp;#010;&amp;#035;&amp;#052;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#050;&amp;#098;&amp;#050;&amp;#099;&amp;#098;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#097;&amp;#114;&amp;#099;&amp;#104;&amp;#095;&amp;#104;&amp;#097;&amp;#110;&amp;#100;&amp;#108;&amp;#101;&amp;#095;&amp;#097;&amp;#108;&amp;#116;&amp;#115;&amp;#116;&amp;#097;&amp;#099;&amp;#107;&amp;#095;&amp;#101;&amp;#120;&amp;#099;&amp;#101;&amp;#112;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#032;&amp;#040;&amp;#115;&amp;#105;&amp;#103;&amp;#099;&amp;#116;&amp;#120;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#102;&amp;#099;&amp;#100;&amp;#048;&amp;#099;&amp;#044;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#097;&amp;#117;&amp;#108;&amp;#116;&amp;#095;&amp;#097;&amp;#100;&amp;#100;&amp;#114;&amp;#061;&amp;#048;&amp;#120;&amp;#056;&amp;#044;&amp;#032;&amp;#115;&amp;#116;&amp;#097;&amp;#099;&amp;#107;&amp;#095;&amp;#111;&amp;#118;&amp;#102;&amp;#061;&amp;#048;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#101;&amp;#120;&amp;#099;&amp;#101;&amp;#112;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#045;&amp;#120;&amp;#056;&amp;#054;&amp;#046;&amp;#099;&amp;#058;&amp;#049;&amp;#049;&amp;#054;&amp;#051;&amp;#013;&amp;#010;&amp;#035;&amp;#053;&amp;#032;&amp;#032;&amp;#060;&amp;#115;&amp;#105;&amp;#103;&amp;#110;&amp;#097;&amp;#108;&amp;#032;&amp;#104;&amp;#097;&amp;#110;&amp;#100;&amp;#108;&amp;#101;&amp;#114;&amp;#032;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#101;&amp;#100;&amp;#062;&amp;#013;&amp;#010;&amp;#035;&amp;#054;&amp;#032;&amp;#032;&amp;#097;&amp;#108;&amp;#108;&amp;#111;&amp;#099;&amp;#095;&amp;#108;&amp;#097;&amp;#114;&amp;#103;&amp;#101;&amp;#095;&amp;#105;&amp;#110;&amp;#110;&amp;#101;&amp;#114;&amp;#032;&amp;#040;&amp;#118;&amp;#116;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#061;&amp;#060;&amp;#118;&amp;#097;&amp;#108;&amp;#117;&amp;#101;&amp;#032;&amp;#111;&amp;#112;&amp;#116;&amp;#105;&amp;#109;&amp;#105;&amp;#115;&amp;#101;&amp;#100;&amp;#032;&amp;#111;&amp;#117;&amp;#116;&amp;#062;&amp;#044;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#105;&amp;#122;&amp;#101;&amp;#061;&amp;#060;&amp;#118;&amp;#097;&amp;#108;&amp;#117;&amp;#101;&amp;#032;&amp;#111;&amp;#112;&amp;#116;&amp;#105;&amp;#109;&amp;#105;&amp;#115;&amp;#101;&amp;#100;&amp;#032;&amp;#111;&amp;#117;&amp;#116;&amp;#062;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#045;&amp;#108;&amp;#111;&amp;#115;&amp;#046;&amp;#099;&amp;#058;&amp;#051;&amp;#054;&amp;#056;&amp;#013;&amp;#010;&amp;#035;&amp;#055;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#055;&amp;#052;&amp;#101;&amp;#049;&amp;#055;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#103;&amp;#099;&amp;#095;&amp;#097;&amp;#108;&amp;#108;&amp;#111;&amp;#099;&amp;#095;&amp;#111;&amp;#098;&amp;#106;&amp;#095;&amp;#110;&amp;#111;&amp;#108;&amp;#111;&amp;#099;&amp;#107;&amp;#032;&amp;#040;&amp;#118;&amp;#116;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#097;&amp;#102;&amp;#057;&amp;#052;&amp;#056;&amp;#044;&amp;#032;&amp;#115;&amp;#105;&amp;#122;&amp;#101;&amp;#061;&amp;#048;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#045;&amp;#103;&amp;#099;&amp;#046;&amp;#099;&amp;#058;&amp;#051;&amp;#050;&amp;#049;&amp;#057;&amp;#013;&amp;#010;&amp;#035;&amp;#056;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#055;&amp;#053;&amp;#052;&amp;#050;&amp;#056;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#103;&amp;#099;&amp;#095;&amp;#097;&amp;#108;&amp;#108;&amp;#111;&amp;#099;&amp;#095;&amp;#118;&amp;#101;&amp;#099;&amp;#116;&amp;#111;&amp;#114;&amp;#032;&amp;#040;&amp;#118;&amp;#116;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#097;&amp;#102;&amp;#057;&amp;#052;&amp;#056;&amp;#044;&amp;#032;&amp;#115;&amp;#105;&amp;#122;&amp;#101;&amp;#061;&amp;#049;&amp;#052;&amp;#055;&amp;#054;&amp;#056;&amp;#049;&amp;#056;&amp;#054;&amp;#052;&amp;#044;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#097;&amp;#120;&amp;#095;&amp;#108;&amp;#101;&amp;#110;&amp;#103;&amp;#116;&amp;#104;&amp;#061;&amp;#049;&amp;#056;&amp;#052;&amp;#054;&amp;#048;&amp;#050;&amp;#051;&amp;#049;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#115;&amp;#103;&amp;#101;&amp;#110;&amp;#045;&amp;#103;&amp;#099;&amp;#046;&amp;#099;&amp;#058;&amp;#051;&amp;#052;&amp;#051;&amp;#055;&amp;#013;&amp;#010;&amp;#035;&amp;#057;&amp;#032;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#099;&amp;#098;&amp;#048;&amp;#098;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#063;&amp;#063;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#048;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#057;&amp;#055;&amp;#100;&amp;#053;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#063;&amp;#063;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#049;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#099;&amp;#054;&amp;#057;&amp;#053;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#063;&amp;#063;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#050;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#099;&amp;#050;&amp;#097;&amp;#056;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#063;&amp;#063;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#051;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#056;&amp;#100;&amp;#057;&amp;#100;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#063;&amp;#063;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#052;&amp;#032;&amp;#048;&amp;#120;&amp;#098;&amp;#055;&amp;#050;&amp;#101;&amp;#056;&amp;#102;&amp;#100;&amp;#054;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#063;&amp;#063;&amp;#032;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#053;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#048;&amp;#054;&amp;#053;&amp;#051;&amp;#049;&amp;#056;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#106;&amp;#105;&amp;#116;&amp;#095;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#095;&amp;#105;&amp;#110;&amp;#118;&amp;#111;&amp;#107;&amp;#101;&amp;#032;&amp;#040;&amp;#109;&amp;#101;&amp;#116;&amp;#104;&amp;#111;&amp;#100;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#051;&amp;#048;&amp;#098;&amp;#100;&amp;#099;&amp;#044;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#061;&amp;#048;&amp;#120;&amp;#048;&amp;#044;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#112;&amp;#097;&amp;#114;&amp;#097;&amp;#109;&amp;#115;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#102;&amp;#100;&amp;#049;&amp;#097;&amp;#097;&amp;#102;&amp;#099;&amp;#044;&amp;#032;&amp;#101;&amp;#120;&amp;#099;&amp;#061;&amp;#048;&amp;#120;&amp;#048;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#109;&amp;#105;&amp;#110;&amp;#105;&amp;#046;&amp;#099;&amp;#058;&amp;#053;&amp;#051;&amp;#057;&amp;#050;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#054;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#097;&amp;#057;&amp;#097;&amp;#097;&amp;#048;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#095;&amp;#105;&amp;#110;&amp;#118;&amp;#111;&amp;#107;&amp;#101;&amp;#032;&amp;#040;&amp;#109;&amp;#101;&amp;#116;&amp;#104;&amp;#111;&amp;#100;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#051;&amp;#048;&amp;#098;&amp;#100;&amp;#099;&amp;#044;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#061;&amp;#048;&amp;#120;&amp;#048;&amp;#044;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#112;&amp;#097;&amp;#114;&amp;#097;&amp;#109;&amp;#115;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#102;&amp;#100;&amp;#049;&amp;#097;&amp;#097;&amp;#102;&amp;#099;&amp;#044;&amp;#032;&amp;#101;&amp;#120;&amp;#099;&amp;#061;&amp;#048;&amp;#120;&amp;#048;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#046;&amp;#099;&amp;#058;&amp;#050;&amp;#055;&amp;#048;&amp;#057;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#055;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#049;&amp;#097;&amp;#100;&amp;#049;&amp;#102;&amp;#054;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#095;&amp;#101;&amp;#120;&amp;#101;&amp;#099;&amp;#095;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#040;&amp;#109;&amp;#101;&amp;#116;&amp;#104;&amp;#111;&amp;#100;&amp;#061;&amp;#048;&amp;#120;&amp;#097;&amp;#051;&amp;#051;&amp;#048;&amp;#098;&amp;#100;&amp;#099;&amp;#044;&amp;#032;&amp;#097;&amp;#114;&amp;#103;&amp;#115;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#054;&amp;#099;&amp;#048;&amp;#048;&amp;#054;&amp;#051;&amp;#056;&amp;#044;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#120;&amp;#099;&amp;#061;&amp;#048;&amp;#120;&amp;#048;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#046;&amp;#099;&amp;#058;&amp;#051;&amp;#056;&amp;#051;&amp;#056;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#056;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#048;&amp;#098;&amp;#098;&amp;#053;&amp;#048;&amp;#049;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#095;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#095;&amp;#104;&amp;#097;&amp;#110;&amp;#100;&amp;#108;&amp;#101;&amp;#114;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#103;&amp;#099;&amp;#061;&amp;#050;&amp;#044;&amp;#032;&amp;#097;&amp;#114;&amp;#103;&amp;#118;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#102;&amp;#100;&amp;#049;&amp;#097;&amp;#099;&amp;#101;&amp;#052;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#100;&amp;#114;&amp;#105;&amp;#118;&amp;#101;&amp;#114;&amp;#046;&amp;#099;&amp;#058;&amp;#057;&amp;#057;&amp;#057;&amp;#013;&amp;#010;&amp;#035;&amp;#049;&amp;#057;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#103;&amp;#099;&amp;#061;&amp;#050;&amp;#044;&amp;#032;&amp;#097;&amp;#114;&amp;#103;&amp;#118;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#102;&amp;#100;&amp;#049;&amp;#097;&amp;#099;&amp;#101;&amp;#052;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#100;&amp;#114;&amp;#105;&amp;#118;&amp;#101;&amp;#114;&amp;#046;&amp;#099;&amp;#058;&amp;#049;&amp;#056;&amp;#051;&amp;#054;&amp;#013;&amp;#010;&amp;#035;&amp;#050;&amp;#048;&amp;#032;&amp;#048;&amp;#120;&amp;#048;&amp;#056;&amp;#048;&amp;#053;&amp;#098;&amp;#051;&amp;#056;&amp;#056;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#095;&amp;#119;&amp;#105;&amp;#116;&amp;#104;&amp;#095;&amp;#111;&amp;#112;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#103;&amp;#099;&amp;#061;&amp;#050;&amp;#044;&amp;#032;&amp;#097;&amp;#114;&amp;#103;&amp;#118;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#102;&amp;#100;&amp;#049;&amp;#097;&amp;#099;&amp;#101;&amp;#052;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#046;&amp;#099;&amp;#058;&amp;#054;&amp;#054;&amp;#013;&amp;#010;&amp;#035;&amp;#050;&amp;#049;&amp;#032;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#103;&amp;#099;&amp;#061;&amp;#050;&amp;#044;&amp;#032;&amp;#097;&amp;#114;&amp;#103;&amp;#118;&amp;#061;&amp;#048;&amp;#120;&amp;#098;&amp;#102;&amp;#100;&amp;#049;&amp;#097;&amp;#099;&amp;#101;&amp;#052;&amp;#041;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#046;&amp;#099;&amp;#058;&amp;#057;&amp;#055;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#013;&amp;#010;&amp;#071;&amp;#111;&amp;#116;&amp;#032;&amp;#097;&amp;#032;&amp;#083;&amp;#073;&amp;#071;&amp;#083;&amp;#069;&amp;#071;&amp;#086;&amp;#032;&amp;#119;&amp;#104;&amp;#105;&amp;#108;&amp;#101;&amp;#032;&amp;#101;&amp;#120;&amp;#101;&amp;#099;&amp;#117;&amp;#116;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#110;&amp;#097;&amp;#116;&amp;#105;&amp;#118;&amp;#101;&amp;#032;&amp;#099;&amp;#111;&amp;#100;&amp;#101;&amp;#046;&amp;#032;&amp;#084;&amp;#104;&amp;#105;&amp;#115;&amp;#032;&amp;#117;&amp;#115;&amp;#117;&amp;#097;&amp;#108;&amp;#108;&amp;#121;&amp;#032;&amp;#105;&amp;#110;&amp;#100;&amp;#105;&amp;#099;&amp;#097;&amp;#116;&amp;#101;&amp;#115;&amp;#013;&amp;#010;&amp;#097;&amp;#032;&amp;#102;&amp;#097;&amp;#116;&amp;#097;&amp;#108;&amp;#032;&amp;#101;&amp;#114;&amp;#114;&amp;#111;&amp;#114;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#032;&amp;#114;&amp;#117;&amp;#110;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#032;&amp;#111;&amp;#114;&amp;#032;&amp;#111;&amp;#110;&amp;#101;&amp;#032;&amp;#111;&amp;#102;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#032;&amp;#110;&amp;#097;&amp;#116;&amp;#105;&amp;#118;&amp;#101;&amp;#032;&amp;#108;&amp;#105;&amp;#098;&amp;#114;&amp;#097;&amp;#114;&amp;#105;&amp;#101;&amp;#115;&amp;#013;&amp;#010;&amp;#117;&amp;#115;&amp;#101;&amp;#100;&amp;#032;&amp;#098;&amp;#121;&amp;#032;&amp;#121;&amp;#111;&amp;#117;&amp;#114;&amp;#032;&amp;#097;&amp;#112;&amp;#112;&amp;#108;&amp;#105;&amp;#099;&amp;#097;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#046;&amp;#013;&amp;#010;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#061;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#065;&amp;#098;&amp;#111;&amp;#114;&amp;#116;&amp;#101;&amp;#100;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;Seven years after the Mono team described their use of the Boehm garbage collector as &lt;a href="http://lists.ximian.com/pipermail/mono-gc-list/2003-August/000012.html"&gt;"an interim measure"&lt;/a&gt;, the SGen collector is still experimental. Hopefully these issues will be resolved and the Mono platform will benefit from a reliable garbage collector in the not too-distant future. However, we cannot help but wonder why the Mono team have not chosen to release a simple but reliable garbage collector that people could use while they wait for SGen to be stabilized. After all, &lt;a href="http://flyingfrogblog.blogspot.com/2010/09/are-multicore-capable-garbage.html"&gt;multicore-friendly garbage collection can be easy&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-5382123616910031215?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/5382123616910031215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=5382123616910031215' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5382123616910031215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5382123616910031215'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/11/mono-28-step-closer-to-reliable.html' title='Mono 2.8: a step closer to a reliable foundation'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-4169791137278856178</id><published>2010-10-27T09:24:00.000-07:00</published><updated>2010-10-27T10:04:59.732-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='asynchronous workflow'/><category scheme='http://www.blogger.com/atom/ns#' term='monad'/><category scheme='http://www.blogger.com/atom/ns#' term='lwt'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='pa_monad'/><category scheme='http://www.blogger.com/atom/ns#' term='asynchronous'/><title type='text'>"The F# Asynchronous Programming Model" by Don Syme et al.</title><content type='html'>&lt;p&gt;The creator of the &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/"&gt;F#&lt;/a&gt; programming language at Microsoft Research in Cambridge, Don Syme, recently had &lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Components-PostAttachments/00-10-07-89-59/async_2D00_padl_2D00_pre_2D00_publication_2D00_draft_2D00_v2.pdf"&gt;a paper&lt;/a&gt; accepted for the &lt;i&gt;Practical Aspects of Declarative Languages&lt;/i&gt; conference. This paper provides a great introduction to asynchronous workflows and the &lt;span class="Apple-style-span"&gt;MailboxProcessor&lt;/span&gt; in &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/"&gt;F#&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In fact, the use of monads to sequence asynchronous operations has a long history. For example, this approach has been used in the &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/"&gt;OCaml&lt;/a&gt; programming language, from which &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/"&gt;F#&lt;/a&gt; is descended, for at least 8 years. Specifically,  &lt;a href="http://ocsigen.org/lwt/"&gt;Jérôme Vouillon's LWT library&lt;/a&gt; for &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/"&gt;OCaml&lt;/a&gt; made asynchronous programming easy. For example, the first &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/"&gt;F#&lt;/a&gt; sample given in this paper:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;async { let! html = getWebPage "http://www.google.com"&lt;br /&gt;        return html.Length }&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;Could have been written in &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/"&gt;OCaml&lt;/a&gt; as follows in 2002:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;getWebPage "http://www.google.com" &gt;&gt;=&lt;br /&gt;String.length&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;In 2005, &lt;a href="http://www.cas.mcmaster.ca/~carette/pa_monad/"&gt;Jacques Carette et al.'s pa_monad syntax extension&lt;/a&gt; even added the same kind of syntactic sugar that &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/"&gt;F#&lt;/a&gt; provides for its asynchronous workflows, allowing the sample to be written in &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/"&gt;OCaml&lt;/a&gt; as:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;perform&lt;br /&gt;  html &lt;-- getWebPage "http://www.google.com"&lt;br /&gt;  return String.length html&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;For more information on asynchronous programming in F#, read &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/"&gt;Visual F# 2010 for Technical Computing&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-4169791137278856178?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/4169791137278856178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=4169791137278856178' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4169791137278856178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4169791137278856178'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/10/f-asynchronous-programming-model-by-don.html' title='&quot;The F# Asynchronous Programming Model&quot; by Don Syme et al.'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-1233258937185502708</id><published>2010-10-20T15:18:00.000-07:00</published><updated>2011-05-01T15:05:35.588-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parallel'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrent'/><title type='text'>What is the difference between parallel and concurrent programming?</title><content type='html'>&lt;p&gt;Concurrent programming regards operations that appear to overlap and is primarily concerned with the complexity that arises due to non-deterministic control flow. The quantitative costs associated with concurrent programs are typically both throughput and latency. Concurrent programs are often IO bound but not always, e.g. concurrent garbage collectors are entirely on-CPU. The pedagogical example of a concurrent program is a web crawler. This program initiates requests for web pages and accepts the responses concurrently as the results of the downloads become available, accumulating a set of pages that have already been visited. Control flow is non-deterministic because the responses are not necessarily received in the same order each time the program is run. This characteristic can make it very hard to debug concurrent programs. Some applications are fundamentally concurrent, e.g. web servers must handle client connections concurrently. &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt; is a language designed specifically for distributed concurrent programming with fault tolerance but many other languages provide features for concurrent programming, such as asynchronous workflows in &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;the F# programming language&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Parallel programming concerns operations that are overlapped for the specific goal of improving throughput. The difficulties of concurrent programming are evaded by making control flow deterministic. Typically, programs spawn sets of child tasks that run in parallel and the parent task only continues once every subtask has finished. This makes parallel programs much easier to debug. The hard part of parallel programming is performance optimization with respect to issues such as granularity and communication. The latter is still an issue in the context of multicores because there is a considerable cost associated with transferring data from one cache to another. Dense matrix-matrix multiply is a pedagogical example of parallel programming and it can be solved efficiently by using Strassen's divide-and-conquer algorithm and attacking the sub-problems in parallel. &lt;a href="http://supertech.csail.mit.edu/cilk/"&gt;Cilk&lt;/a&gt; is pioneered the most promising techniques for high-performance parallel programming on shared-memory computers (including multicores) and its technology is now offered by Intel in their Threaded Building Blocks (TBB) and Microsoft in .NET 4. So this is also easily accessible from &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;the F# programming language&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-1233258937185502708?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/1233258937185502708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=1233258937185502708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1233258937185502708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1233258937185502708'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/10/what-is-difference-between-parallel-and.html' title='What is the difference between parallel and concurrent programming?'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-4851132515557351505</id><published>2010-10-20T10:41:00.001-07:00</published><updated>2010-10-20T14:46:36.972-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='don syme'/><category scheme='http://www.blogger.com/atom/ns#' term='parallel'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrent'/><title type='text'>Don Syme on "Functional approaches to parallelism and concurrency"</title><content type='html'>&lt;p&gt;Don Syme, creator of the F# programming language, recently gave a superb lecture on parallel and concurrent programming using F# at QCon 2010. Video and slides hosted by InfoQ &lt;a href="http://www.infoq.com/presentations/Functional-Approaches-To-Parallelism"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Parallel programming continues to be a hot topic in the face of multicore computing but, as Don points out, the world is also moving steadily towards more concurrent programming.&lt;/p&gt;&lt;p&gt;Work continues on our forthcoming "Multicore .NET" book that studies parallel programming using C# and F# in detail...&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-4851132515557351505?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/4851132515557351505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=4851132515557351505' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4851132515557351505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4851132515557351505'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/10/don-syme-on-functional-approaches-to.html' title='Don Syme on &quot;Functional approaches to parallelism and concurrency&quot;'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-3015444876396029684</id><published>2010-10-19T02:22:00.001-07:00</published><updated>2010-10-22T05:42:41.781-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gc pause'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrent garbage collector'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='latency'/><title type='text'>Can you repro this 64-bit .NET GC bug?</title><content type='html'>&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; &lt;a href="http://blogs.msdn.com/b/maoni/"&gt;Maoni Stephens&lt;/a&gt; of Microsoft, the author of this new "Background" garbage collector in .NET 4, has now reproduced the bug and acknowledged that we really are seeing GC pauses lasting several minutes.&lt;/p&gt;&lt;p&gt;Whilst developing low latency software on .NET, we have discovered a serious bug in the .NET 4 concurrent workstation garbage collector that can cause applications to hang for up to several minutes at a time.&lt;/p&gt;&lt;p&gt;On three of our machines the following simple C# program causes the GC to leak memory until none remains and a single mammoth GC cycle kicks in, stalling the program for several minutes (!) while 11Gb of heap is recycled:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;static void Main(string[] args) {&lt;/pre&gt;&lt;pre&gt;  var q = new System.Collections.Generic.Queue&lt;system.object&gt;(); &lt;/system.object&gt;&lt;/pre&gt;&lt;pre&gt;&lt;system.object&gt;&lt;/system.object&gt;  while (true) { &lt;/pre&gt;&lt;pre&gt;    q.Enqueue(0); &lt;/pre&gt;&lt;pre&gt;    if (q.Count &gt; 1000000) &lt;/pre&gt;&lt;pre&gt;      q.Dequeue(); &lt;/pre&gt;&lt;pre&gt;  } &lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;You need to compile for x64 on a 64-bit Windows OS with .NET 4 and run with the default (concurrent workstation) GC using the default (interactive) latency setting.&lt;/p&gt;&lt;p&gt;Here's what the Task Manager looks like when running this program on this machine:&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_NMRkpon4Ps0/TL1luhRQlAI/AAAAAAAAAJ4/w6v5Cn8knSE/s1600/GCBug.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 307px;" src="http://2.bp.blogspot.com/_NMRkpon4Ps0/TL1luhRQlAI/AAAAAAAAAJ4/w6v5Cn8knSE/s400/GCBug.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5529687767359984642" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Note that 11Gb of heap have been leaked here when this program requires no more than 100Mb of memory.&lt;/p&gt;&lt;p&gt;We have now accumulated around a dozen repros of this bug, written in F# as well as C#, and it appears to be related to a bug in the GC write barrier when most of gen0 survives. However, Microsoft have not yet been able to reproduce it. Can you?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-3015444876396029684?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/3015444876396029684/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=3015444876396029684' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3015444876396029684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3015444876396029684'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/10/can-you-repro-this-64-bit-net-gc-bug.html' title='Can you repro this 64-bit .NET GC bug?'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_NMRkpon4Ps0/TL1luhRQlAI/AAAAAAAAAJ4/w6v5Cn8knSE/s72-c/GCBug.png' height='72' width='72'/><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-606787494673828599</id><published>2010-10-16T13:22:00.000-07:00</published><updated>2010-10-16T17:45:23.959-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='arm'/><category scheme='http://www.blogger.com/atom/ns#' term='intel'/><category scheme='http://www.blogger.com/atom/ns#' term='netbook'/><category scheme='http://www.blogger.com/atom/ns#' term='share'/><category scheme='http://www.blogger.com/atom/ns#' term='market'/><category scheme='http://www.blogger.com/atom/ns#' term='sales'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>ARM-based iPads choke Intel-based netbook sales</title><content type='html'>&lt;p&gt;The &lt;a href="http://www.guardian.co.uk/technology/2010/oct/14/ipad-netbook-sales"&gt;recent news&lt;/a&gt; that Apple are selling around 18 million of their ARM-based iPads per year reminded us of our article &lt;a href="http://flyingfrogblog.blogspot.com/2010/01/will-intel-lose-computer-market-to-arm.html"&gt;Will Intel lose the computer market to ARM in 2012?&lt;/a&gt; from January. Following their success, there are now a growing number of competitors itching to release ARM-based tablet PCs of their own, like &lt;a href="http://www.marvell.com/company/news/press_detail.html?releaseID=1397"&gt;Marvell's $99 Moby tablet&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Compare just those iPad sales to the 35 million netbooks of all brands sold in 2009 and the &lt;a href="http://news.softpedia.com/news/Netbook-Sales-to-Reach-36-Million-in-2010-151301.shtml"&gt;predicted&lt;/a&gt; 36 million netbooks to be sold in 2010 and it looks as though Intel may at least lose the mobile market to ARM in 2012.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-606787494673828599?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/606787494673828599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=606787494673828599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/606787494673828599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/606787494673828599'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/10/arm-based-ipads-choke-intel-based.html' title='ARM-based iPads choke Intel-based netbook sales'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-3425205495343900337</id><published>2010-10-10T14:00:00.000-07:00</published><updated>2010-10-10T14:30:57.475-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simon marlow'/><category scheme='http://www.blogger.com/atom/ns#' term='ghc'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrent garbage collector'/><title type='text'>Towards concurrent garbage collection for GHC</title><content type='html'>&lt;p&gt;Simon Marlow of Microsoft Research recently published a blog post entitled &lt;a href="http://hackage.haskell.org/trac/ghc/blog/new-gc-preview"&gt;First results from GHC's new garbage collector&lt;/a&gt;. As his beautiful graphs show so clearly, this is a first step towards concurrent garbage collection. The blog post describes this advancement entirely from the perspective of throughput because the ability to collect per-thread nursery generations independently removes some of the blocking that was wasting mutator time in the previous version.&lt;/p&gt;&lt;p&gt;However, we believe that concurrent programming may become a killer application domain for Haskell and, in that context, latency can be critical. If GHC's garbage collector is made more concurrent, by allowing the old generation to be collected independently as well, then pause times could be greatly reduced and Haskell would have a considerable advantage over competing technologies like .NET.&lt;/p&gt;&lt;p&gt;We have found that even the best-behaved .NET programs that allocate still suffer GC pauses of around 20ms, over an order of magnitude longer than the 600µs pause times indicated on the graphs for this new version of GHC. Real .NET applications that were not designed from the ground up to attain low latency suffer stalls lasting several seconds!&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-3425205495343900337?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/3425205495343900337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=3425205495343900337' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3425205495343900337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3425205495343900337'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/10/towards-concurrent-garbage-collection.html' title='Towards concurrent garbage collection for GHC'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-1465604117426794377</id><published>2010-09-26T04:50:00.001-07:00</published><updated>2010-10-09T15:16:35.859-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='boehm'/><category scheme='http://www.blogger.com/atom/ns#' term='hlvm'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Lessons learned from HLVM</title><content type='html'>&lt;p&gt;Although our &lt;a href="http://www.ffconsultancy.com/ocaml/hlvm/"&gt;HLVM&lt;/a&gt; project is intended to bring modern VM techniques to modern programming languages without requiring any new research, we have ended up producing several enlightening new results. This article takes a look at some of the weird and wonderful techniques we used in &lt;a href="http://www.ffconsultancy.com/ocaml/hlvm/"&gt;HLVM&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;font-size:130%;"&gt;&lt;strong&gt;GC as a metaprogram (good!)&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Whereas most VMs use a garbage collector written in C or C++, the GC in HLVM is written in its own intermediate representation. This unusual design has a variety of benefits:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The GC acts as a test for the compiler.&lt;/li&gt;&lt;li&gt;The GC benefits from improvements we make to the compiler.&lt;/li&gt;&lt;li&gt;The GC is simplified by being able to use features like tail call elimination and higher-order functions.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Overall, implementing the GC in HLVM's own IR proved to be hugely beneficial: the GC was very easy to write and is easy to maintain.&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;font-size:130%;"&gt;&lt;strong&gt;Fat references (bad!)&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Most VMs store header data in each heap-allocated block that describes the size and type of a value in order to allow the garbage collector to traverse it. In HLVM, we moved this header data into the reference itself. This allows C data structures to be used directly without having to be copied in order add the header, simplifying and improving the efficiency of the foreign function interface (FFI).&lt;/p&gt;&lt;p&gt;This adds a 4-word space overhead for duplicated references. Fortunately, duplicate references are rare and no significant space overhead has ever been observed in practice.&lt;/p&gt;&lt;p&gt;However, there are two disadvantages. Firstly, we have observed significant performance degradation as fat references are pushed onto the stadow stack, requiring 4× more bandwidth than 1-word references would. Secondly, our fat references cannot be updated atomically so our VM is not memory safe.&lt;/p&gt;&lt;p&gt;Lack of memory safety is a major concern and the best solution we have come up with to date is to resort to 1-word references as pointers to heap-allocated header information. Note that HLVM currently calls &lt;span style="font-family:courier new;"&gt;malloc&lt;/span&gt; twice for each allocation (once to allocate a mark bit and again to allocate the actual data) so moving the header information back into the heap need not require more allocations. The obvious solution of placing the header alongside the mark bit would incur false sharing when the GC thread writes to the mark bit and a mutator reads the header information. If that proves to be a problem then a better solution might be to store an index that can be used to look up the mark bit and header data from two separate arrays.&lt;/p&gt;&lt;p&gt;&lt;p&gt;&lt;span style="font-family:arial;font-size:130%;"&gt;&lt;strong&gt;Shadow stacks (adequate!)&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Xavier Leroy dismissed our proposed shadow stack, saying "&lt;a href="http://caml.inria.fr/pub/ml-archives/caml-list/2009/03/3a77bfcca0f90b763d127d1581d6a2f1.en.html"&gt;probably the worst approach performance-wise; even a conservative GC should work better&lt;/a&gt;". Our motivation for using shadow stacks was always simplicity rather than performance. Shadow stacks are simply because LLVM's GC support is highly experimental (to date, only two people claim to have managed to get it to work) and &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.5570"&gt;shadow stacks facilitate accurate GC in an uncooperative environment&lt;/a&gt;). In fact, our results have already proven that Xavier's statement is not true in general and, in fact, we believe it may even be wrong in general.&lt;/p&gt;&lt;p&gt;Specifically, of the six benchmarks from our benchmark suite than handle references in the inner loop (thus incurring manipulation of the shadow stack), HLVM is significantly faster than OCaml on four of them. So our shadow stack cannot be degrading performance &lt;em&gt;that&lt;/em&gt; much! Moreover, OCaml is 9× faster than HLVM on our &lt;em&gt;n&lt;/em&gt;-queens benchmark only because its generational collector allows short-lived values to be recycled very efficiently and that has nothing to do with the shadow stack.&lt;/p&gt;&lt;p&gt;So we believe shadow stacks are an adequate solution.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-1465604117426794377?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/1465604117426794377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=1465604117426794377' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1465604117426794377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1465604117426794377'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/09/lessons-learned-from-hlvm.html' title='Lessons learned from HLVM'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-8983900971669856023</id><published>2010-09-25T04:41:00.000-07:00</published><updated>2010-09-25T16:42:03.737-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='boehm'/><category scheme='http://www.blogger.com/atom/ns#' term='conservative gc'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>The effectiveness of Boehm's GC</title><content type='html'>&lt;p&gt;Many people still seem to be trying to use &lt;a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/"&gt;Boehm's garbage collector&lt;/a&gt;. This is surprising because that GC is &lt;em&gt;conservative&lt;/em&gt;, meaning it is incapable of accurately distinguishing between integers and pointers and, consequently, it is prone to memory leaks due to false positives where integers are assumed to be pointers into an allocated heap block, preventing the block from being reclaimed. Consequently, Boehm's GC is a notorious source of memory leaks.&lt;/p&gt;&lt;p&gt;Moreover, 32-bit machines with 4Gb of RAM and programs that use a significant proportion of that RAM are still very common and the proportion of the address space in use is, therefore, high so the probability of false positives is very high.&lt;/p&gt;&lt;p&gt;Imagine a 32-bit program using 40Mb of heap contains a random integer. The probability of that random integer coincidentally pointing into an allocated heap block is approximately 1% because 1% of the 4Gb address space is covered by heap blocks. Now imagine a 32-bit program containing &lt;em&gt;n&lt;/em&gt; random ints and using a proportion &lt;em&gt;p&lt;/em&gt; of the address space. The probability that one or more of those ints point into allocated heap blocks is &lt;em&gt;1-(1-p)&lt;sup&gt;n&lt;/sup&gt;&lt;/em&gt;. In our previous example, if there were 100 random ints then the probability of a false positive is a whopping 63%!&lt;/p&gt;&lt;p&gt;This is why 32-bit programs that use Boehm's GC are so prone to memory leaks. Hash tables are particularly susceptible to this problem because hashes are effectively random ints and the spines of hash tables are large heap blocks. Indeed, this appears to explain &lt;a href="http://flyingfrogblog.blogspot.com/2010/07/mono-24-still-leaking-like-sieve.html"&gt;the memory leak we observed&lt;/a&gt; when using hash tables on Mono back in July.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-8983900971669856023?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/8983900971669856023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=8983900971669856023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8983900971669856023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8983900971669856023'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/09/effectiveness-of-boehms-gc.html' title='The effectiveness of Boehm&apos;s GC'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-2486025204826444148</id><published>2010-09-19T13:25:00.000-07:00</published><updated>2010-09-19T16:29:42.929-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='multicore'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrent garbage collector'/><category scheme='http://www.blogger.com/atom/ns#' term='parallel garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Are multicore-capable garbage collectors hard to write?</title><content type='html'>&lt;p&gt;In this era of multicore computing, garbage collectors need to allow user threads (aka &lt;i&gt;mutators&lt;/i&gt;) to run in parallel on separate cores simultaneously in order to facilitate efficient shared memory parallel programming.&lt;/p&gt;&lt;p&gt;There are two relevant phrases from garbage collection terminology here:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Parallel GC&lt;/b&gt; means the garbage collector itself has been parallelised in order to speed up garbage collections. For example, a stop-the-world collector might traverse the heap in parallel when marking in an attempt to reduce pause times.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;Concurrent GC&lt;/b&gt; means the garbage collector runs at the same time as the user threads (aka &lt;em&gt;mutators&lt;/em&gt;). For example, Dijkstra's algorithm and derivatives like Doligez-Leroy use fine-grained synchronization to keep a concurrently-running collector apprised of the constantly-changing heap topology.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;However, we are talking about neither parallel GC nor concurrent GC but, rather, the simpler challenge of just allowing mutators to run in parallel. In the absence of any established terminology, we call any GC that allows mutator threads to run in parallel with each other a &lt;em&gt;multicore-friendly&lt;/em&gt; garbage collector.&lt;/p&gt;&lt;p&gt;Frustratingly, many people are perpetuating the myth that it is difficult to write parallel or concurrent or even just multicore-friendly garbage collectors. In particular, this is happening around the OCaml language as a result of &lt;a href="http://caml.inria.fr/pub/ml-archives/caml-list/2002/11/64c14acb90cb14bedb2cacb73338fb15.en.html"&gt;Xavier Leroy's (in)famous "standard lecture on threads" from 2002&lt;/a&gt; where he explained that they were not creating a multicore-friendly garbage collector for OCaml because multicores would never become popular and he described Intel's hyperthreading as "the last convulsive movement of SMP's corpse". Xavier is a great guy and had done a lot of great work but, of course, he was completely wrong about this. Not only are multicores ubiquitous and hyperthreading is very common but shared memory parallelism is here to stay: even if distributed parallelism becomes essential in the future when cache coherence breaks down we will be doing distributed parallel programming between multicores because shared memory parallelism is so much more efficient than distributed parallelism most of the time.&lt;/p&gt;&lt;p&gt;The JVM and .NET CLR obviously provide multicore-friendly garbage collectors so people sometimes assert that creating such a garbage collector requires huge resources and is beyond a small group such as the OCaml team at INRIA. This is simply not true. The simplest multicore-friendly garbage collector design is a stop-the-world collector that pauses all user threads while the entire heap is marked and swept safe in the knowledge that the heap topology is static. Our own &lt;a href="http://www.ffconsultancy.com/ocaml/hlvm/"&gt;HLVM&lt;/a&gt; project currently uses exactly this design and it took just a few days to write and is under 100 lines of code! And we are not alone. Simon Marlow has written several far more sophisticated multicore-friendly garbage collectors for the &lt;a href="http://www.haskell.org/ghc/"&gt;Glasgow Haskell Compiler&lt;/a&gt; by himself. The &lt;a href="http://www.polyml.org/"&gt;PolyML&lt;/a&gt; project developed a multicore-friendly garbage collector without benefit of funding from a multinational corporation. Same for &lt;a href="http://manticore.cs.uchicago.edu/"&gt;Manticore&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Even some of the more sophisticated mostly-concurrent garbage collector designs are remarkably simple. For example, the &lt;a href="http://doc.cat-v.org/inferno/concurrent_gc/"&gt;Very Concurrent Garbage Collector (VCGC)&lt;/a&gt; uses a breathtakingly-elegant approach based around three epochs (instead of the usual tricolor marking scheme) that completely avoids the error-prone and inefficient fine-grained synchronization originally proposed by Dijkstra and followed by almost everyone else. The entire algorithm for this mostly concurrent garbage collector can be expressed in a single page of code!&lt;/p&gt;&lt;p&gt;So please do not let these myths put you off trying to write your own multicore-friendly garbage collector: this is an interesting, rewarding and entirely tractable challenge!&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-2486025204826444148?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/2486025204826444148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=2486025204826444148' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2486025204826444148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/2486025204826444148'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/09/are-multicore-capable-garbage.html' title='Are multicore-capable garbage collectors hard to write?'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-1039669149230669776</id><published>2010-09-12T02:38:00.000-07:00</published><updated>2010-09-12T03:35:36.208-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='erik meijer'/><category scheme='http://www.blogger.com/atom/ns#' term='parallel programming'/><category scheme='http://www.blogger.com/atom/ns#' term='burton smith'/><category scheme='http://www.blogger.com/atom/ns#' term='data parallel haskell'/><title type='text'>Burton Smith vs Erik Meijer</title><content type='html'>&lt;p&gt;We were recently led to &lt;a href="http://channel9.msdn.com/shows/Going+Deep/E2E-Erik-Meijer-and-Burton-Smith-Concurrency-Parallelism-and-Programming/"&gt;a fascinating Channel 9 interview&lt;/a&gt; where the insideous Erik Meijer walks in on parallelism-expert &lt;a href="http://en.wikipedia.org/wiki/Burton_Smith"&gt;Burton Smith&lt;/a&gt;, culminating in a fight the likes of which have not been seen since &lt;a href="http://www.express.co.uk/posts/view/113527"&gt;Chris Curry vs Sir Clive Sinclair&lt;/a&gt; in the Baron of Beef here in Cambridge.&lt;/p&gt;&lt;p&gt;A pragmatic Burton points out that lazy evaluation renders performance unpredictable and that, in turn, makes it impossible to tune the granularity of parallel programs to ensure that more effort is spent doing actual work than is wasted administering parallel tasks. The puritanical Erik points out that strictness is essentially another form of side effect because it affects issues such as non-termination. The conclusion is irreconcilable differences between what parallel programming requires and what purely functional programming can provide.&lt;/p&gt;&lt;p&gt;Erik and Burton were joined by an elephant in the room though: caches. They are the main difference between supercomputers and multicores and are a game changer, yet people do not discuss the effect caches have on programming and that effect will only grow as the memory gap continues to widen. Today, effective utilization of caches offers an order of magnitude in performance yet their effective use from purely functional languages like Haskell is essentially impossible precisely because memory has been successfully abstracted away. Indeed, as &lt;a href="http://flyingfrogblog.blogspot.com/2010/06/regular-shape-polymorphic-parallel.html"&gt;we have explained before&lt;/a&gt;, this not only remains a show-stopping unsolved problem for parallel Haskell but is not even being addressed by researchers. Today's state-of-the-art advice for multicore programmers is still to use mutable data structures in order to ensure caches are used effectively based upon the quantification of asymptotic &lt;em&gt;cache complexity&lt;/em&gt; in the context of a simple theoretical model of CPU caches.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-1039669149230669776?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/1039669149230669776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=1039669149230669776' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1039669149230669776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1039669149230669776'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/09/burton-smith-vs-erik-meijer.html' title='Burton Smith vs Erik Meijer'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-168427145857419251</id><published>2010-08-10T06:43:00.000-07:00</published><updated>2010-08-10T08:17:56.918-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='martin odersky'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>New Scala consultancy company</title><content type='html'>&lt;p&gt;We have uncovered an interesting development since publishing &lt;a href="http://flyingfrogblog.blogspot.com/2010/08/scala-is-foremost-industrial-language.html"&gt;our previous article&lt;/a&gt; about Martin Odersky's claim that Scala is "foremost an industrial language". Apparently, Martin Odersky stated at &lt;a href="http://days2010.scala-lang.org/node/138/170"&gt;Scala Days 2010&lt;/a&gt; that he intends to create a startup offering commercial Scala support. He also mentioned it in a comment &lt;a href="http://codemonkeyism.com/scala-unfit-development/"&gt;here&lt;/a&gt;. Needless to say, this would be a huge step forwards for Scala!&lt;/p&gt;&lt;p&gt;As an interesting aside, the &lt;a href="http://www.scala-lang.org/node/1658"&gt;Scala in the Enterprise&lt;/a&gt; web page lists some industrial users of Scala including Électricité de France Trading, Twitter, Xebia, Xerox, FourSquare, Sony, Siemans, GridGain, AppJet, Reaktor, Nature, Managed Gaming Solutions, Tiental, Sygneca, AD Holdings, SAIC, Mimesis Republic and WattzOn.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-168427145857419251?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/168427145857419251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=168427145857419251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/168427145857419251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/168427145857419251'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/08/new-scala-consultancy-company.html' title='New Scala consultancy company'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-659207237666684198</id><published>2010-08-09T13:34:00.000-07:00</published><updated>2010-08-09T16:33:55.244-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='rich hickey'/><category scheme='http://www.blogger.com/atom/ns#' term='joe pamer'/><category scheme='http://www.blogger.com/atom/ns#' term='interview'/><category scheme='http://www.blogger.com/atom/ns#' term='clojure'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>"I think F# is very cool" - Rich Hickey</title><content type='html'>&lt;p&gt;Very interesting video interview &lt;a href="http://channel9.msdn.com/posts/Charles/Emerging-Langs-Clojure-and-F/"&gt;here&lt;/a&gt; with Rich Hickey of Clojure and Joe Pamer of F# side-by-side. When the interviewer asks Rich Hickey what he thinks of F#, he says "I think F# is very cool" and then explains why.&lt;/p&gt;&lt;p&gt;Rich Hickey is, of course, a visionary among programming language developers having single-handedly built a self-sustaining business around his own Clojure language. Remarkably, there are already more Clojure jobs than OCaml jobs according to IT Jobs Watch and there are now twice as many Google searches for Clojure as there are for OCaml:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_NMRkpon4Ps0/TGB4SbWZx1I/AAAAAAAAAJo/SeuPLdXYLZI/s1600/ClojureOCaml.PNG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 400px; height: 201px;" src="http://1.bp.blogspot.com/_NMRkpon4Ps0/TGB4SbWZx1I/AAAAAAAAAJo/SeuPLdXYLZI/s400/ClojureOCaml.PNG" alt="" id="BLOGGER_PHOTO_ID_5503531002621445970" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-659207237666684198?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/659207237666684198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=659207237666684198' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/659207237666684198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/659207237666684198'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/08/i-think-f-is-very-cool-rich-hickey.html' title='&quot;I think F# is very cool&quot; - Rich Hickey'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_NMRkpon4Ps0/TGB4SbWZx1I/AAAAAAAAAJo/SeuPLdXYLZI/s72-c/ClojureOCaml.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-8001932037422037687</id><published>2010-08-07T02:15:00.000-07:00</published><updated>2010-08-07T05:03:37.378-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='industry'/><category scheme='http://www.blogger.com/atom/ns#' term='funding'/><category scheme='http://www.blogger.com/atom/ns#' term='academic'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>"Scala is foremost an industrial language"</title><content type='html'>&lt;p&gt;In a &lt;a href="http://blog.fogus.me/2010/08/06/martinodersky-take5-tolist/"&gt;recent interview&lt;/a&gt; about Scala and Clojure, Martin Odersky of Scala gave some interesting answers including the following:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;Q:&lt;/em&gt; &lt;strong&gt;Rich Hickey is as well-read in the academic papers as anyone, but it’s Scala that has gained the perception as an “academic language”. Why do you think that has happened?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;A:&lt;/em&gt; I think it’s mostly people who want to put Scala down making that comment. They take my EPFL affiliation and the papers we publish as an excuse to attach that label to the language. What’s funny is that often senior industrial Scala programmers get also accused as being academic. All this is rather ironical because Scala is foremost an industrial language with many well known companies using it. By contrast it’s much less taught at universities than Haskell or Lisp, let alone Java!&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This raises the obvious question: in what sense is Scala "foremost an industrial language"?&lt;/p&gt;&lt;p&gt;As we understand it, Scala is developed by an academic team led by professor Odersky at an academic institution with academic funding for the sole purpose of academic research and this has culminated in &lt;a href="http://lamp.epfl.ch/~odersky/"&gt;a new academic paper every 7½ months&lt;/a&gt; on average over the past decade. That is not true of any industrial programming languages. Indeed, from our experiences with Scala this is reflected as a growth in esoteric language features when basic IDE support is neglected. Some people are trying to use Scala in industry, but that is true of many academic languages. Some funding has come from industry, including a surprising grant from Microsoft to update the .NET port of Scala, but that is presumably a tiny fraction of the total funding that has been spent on Scala. So this seems like rather an odd claim.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-8001932037422037687?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/8001932037422037687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=8001932037422037687' title='35 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8001932037422037687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8001932037422037687'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/08/scala-is-foremost-industrial-language.html' title='&quot;Scala is foremost an industrial language&quot;'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>35</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-7407096414695560650</id><published>2010-08-06T15:40:00.000-07:00</published><updated>2010-08-06T15:43:44.262-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='jobs'/><category scheme='http://www.blogger.com/atom/ns#' term='trends'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>More OCaml trends</title><content type='html'>&lt;p&gt;Paolo from Italy pointed out that the number of blog posts on OCaml has continued to increase in recent years (6,420, 10,500 and 12,100 in 2007/8/9 according to Google blog search) and referred to the success of &lt;a href="http://ocamlnews.blogspot.com/2010/04/ocaml-meeting-2010-debriefing.html"&gt;this year's OCaml meeting&lt;/a&gt; with 80 delegates in France. These are certainly encouraging results but it may be worth bringing more data to the table.&lt;/p&gt;&lt;p&gt;Firstly, &lt;a href="http://www.google.co.uk/trends"&gt;Google Trends&lt;/a&gt; can be used to graph the proportion of Google searches for different search terms over time. The following graph shows the trends for the keywords OCaml and F# since 2004:&lt;/p&gt;&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/_NMRkpon4Ps0/TFwbPKGH3QI/AAAAAAAAAJg/pqs4QODbQGU/s1600/OCamlFSharpTrends.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 179px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5502302791961926914" border="0" alt="" src="http://2.bp.blogspot.com/_NMRkpon4Ps0/TFwbPKGH3QI/AAAAAAAAAJg/pqs4QODbQGU/s400/OCamlFSharpTrends.png" /&gt;&lt;/a&gt; As you can see, the proportion of searches for OCaml (blue) is in steady decline whereas the proportion of searches for F# (red) is on the increase and the two crossed over in 2007. In fact, we have found that Google Trends correlates very strongly with our revenue.&lt;/p&gt;&lt;p&gt;Secondly, we can examine statistics about the job market. The following bar chart illustrates the change in UK jobs from 2008 to 2010 for four functional programming languages (source &lt;a href="http://www.itjobswatch.co.uk/"&gt;IT Jobs Watch&lt;/a&gt;):&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_NMRkpon4Ps0/TFwbO9Kl_pI/AAAAAAAAAJY/FCUdIunRXuY/s1600/FunctionalJobs.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 238px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5502302788491017874" border="0" alt="" src="http://3.bp.blogspot.com/_NMRkpon4Ps0/TFwbO9Kl_pI/AAAAAAAAAJY/FCUdIunRXuY/s400/FunctionalJobs.png" /&gt;&lt;/a&gt; As you can see, every language saw tremendous growth in this boom period for functional programming except OCaml which actually saw a decline in the number of jobs on offer.&lt;/p&gt;&lt;p&gt;The deal breaker for us was, of course, revenue. The proportion of our revenue coming from OCaml has fallen steadily from 80% in 2007 to just 10% today.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-7407096414695560650?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/7407096414695560650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=7407096414695560650' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/7407096414695560650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/7407096414695560650'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/08/more-ocaml-trends.html' title='More OCaml trends'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_NMRkpon4Ps0/TFwbPKGH3QI/AAAAAAAAAJg/pqs4QODbQGU/s72-c/OCamlFSharpTrends.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-5642596261345827385</id><published>2010-08-05T17:08:00.000-07:00</published><updated>2010-08-05T17:14:29.943-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='purely functional data structure'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='heap'/><title type='text'>Pure F# now only 2× slower than OCaml</title><content type='html'>&lt;p&gt;One of the concerns expressed by some of the remaining &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt; users, such as Yaron Minsky of Jane St Capital, is the relative performance of &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; in the context of purely functional data structures. Specifically, language implementations like &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt; are heavily optimized for this use case due to their legacy and on-going use for applications such as theorem proving, which benefit greatly from the efficient handling of purely functional data structures. Historically, most users of imperative languages such as Java and C# have not required this kind of performance and, consequently, their implementations have not been optimized for this style of programming. However, the recently released &lt;a href="http://fsharpnews.blogspot.com/2010/02/f-development-with-visual-studio-2010.html"&gt;.NET 4 includes a new garbage collector&lt;/a&gt; and we have found that it provides substantial performance improvements in the context of purely functional data structures which is of particular benefit to &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; developers.&lt;/p&gt;&lt;p&gt;We recently examined the performance of four different purely functional heap implementations across five different benchmarks written in both &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt; and &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; (see &lt;a href="http://fsharpnews.blogspot.com/2010/08/data-structures-heaps.html"&gt;Data structures: heaps&lt;/a&gt;). Where our previous findings in similar benchmarks showed &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; to be 5× slower than &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt;, our new results indicate that &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; on .NET 4 is now only 2× slower than &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt; on average. In one case, a leftist min heap with elements inserted in descending order, &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; even ran 20% faster than &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;This is a surprising and encouraging result not only because it makes &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; competitive for an even wider variety of tasks but because it also implies that Microsoft are taking &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F#&lt;/a&gt; so seriously that they are optimizing the .NET garbage collector for it!&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-5642596261345827385?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/5642596261345827385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=5642596261345827385' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5642596261345827385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5642596261345827385'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/08/pure-f-now-only-2-slower-than-ocaml.html' title='Pure F# now only 2× slower than OCaml'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-6673296700767162245</id><published>2010-08-01T08:47:00.001-07:00</published><updated>2010-08-01T14:29:03.307-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quicksort'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='imperative'/><category scheme='http://www.blogger.com/atom/ns#' term='parallel'/><title type='text'>Parallel generic quicksort in Haskell</title><content type='html'>&lt;p&gt;Haskell has a history of making easy problems difficult. Perhaps the most infamous example was the Sieve of Eratosthenes, which is easily implemented in any imperative language but was so difficult to write in Haskell that almost all of the solutions that had been taught in universities and used in research for the preceding 18 years had been wrong until Melissa O'Neill published a seminal paper &lt;a href="http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf"&gt;&lt;em&gt;The Genuine Sieve of Eratosthenes&lt;/em&gt;&lt;/a&gt; that gave a beautiful description of what they had been doing wrong and how it should be corrected. Melissa's solution was to use a priority queue to implement a rolling wheel of numbers. The correct solution turned out to be 10× longer than &lt;a href="http://fsharpnews.blogspot.com/2010/02/sieve-of-eratosthenes.html"&gt;a much simpler F# solution&lt;/a&gt; and a whopping 100× longer than the original bastardized algorithm in Haskell.&lt;/p&gt;&lt;p&gt;Today, quicksort is the new Sieve of Eratosthenes. Again, the academics have addressed Haskell's failure by &lt;a href="http://www.haskell.org/haskellwiki/Introduction#Quicksort_in_Haskell"&gt;bastardizing the algorithm&lt;/a&gt;, trading orders of magnitude in performance for something that Haskell can express easily:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#113;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#091;&amp;#093;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#061;&amp;#032;&amp;#091;&amp;#093;&amp;#013;&amp;#010;&amp;#113;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#040;&amp;#120;&amp;#058;&amp;#120;&amp;#115;&amp;#041;&amp;#032;&amp;#061;&amp;#032;&amp;#113;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#108;&amp;#116;&amp;#101;&amp;#114;&amp;#032;&amp;#040;&amp;#060;&amp;#032;&amp;#120;&amp;#041;&amp;#032;&amp;#120;&amp;#115;&amp;#041;&amp;#032;&amp;#043;&amp;#043;&amp;#032;&amp;#091;&amp;#120;&amp;#093;&amp;#032;&amp;#043;&amp;#043;&amp;#032;&amp;#113;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#108;&amp;#116;&amp;#101;&amp;#114;&amp;#032;&amp;#040;&amp;#062;&amp;#061;&amp;#032;&amp;#120;&amp;#041;&amp;#032;&amp;#120;&amp;#115;&amp;#041;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;This completely fails to capture the essence of the real quicksort algorithm (see &lt;a href="http://comjnl.oxfordjournals.org/cgi/content/short/5/1/10"&gt;Tony Hoare's original 1962 quicksort paper&lt;/a&gt;) that makes it so efficient. Specifically, the in-place partitioning using swaps.&lt;/p&gt;&lt;p&gt;Faced with the challenge of writing a parallel generic quicksort in Haskell, Jim Apple (who is doing a PhD on Haskell at UC Davis) &lt;a href="http://www.reddit.com/r/coding/comments/codqo/engineering_large_projects_in_a_functional/c0ur3li"&gt;kicked of proceedings with the following code&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#072;&amp;#097;&amp;#115;&amp;#104;&amp;#084;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#032;&amp;#097;&amp;#115;&amp;#032;&amp;#072;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#046;&amp;#073;&amp;#079;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#067;&amp;#111;&amp;#110;&amp;#116;&amp;#114;&amp;#111;&amp;#108;&amp;#046;&amp;#080;&amp;#097;&amp;#114;&amp;#097;&amp;#108;&amp;#108;&amp;#101;&amp;#108;&amp;#046;&amp;#083;&amp;#116;&amp;#114;&amp;#097;&amp;#116;&amp;#101;&amp;#103;&amp;#105;&amp;#101;&amp;#115;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#067;&amp;#111;&amp;#110;&amp;#116;&amp;#114;&amp;#111;&amp;#108;&amp;#046;&amp;#077;&amp;#111;&amp;#110;&amp;#097;&amp;#100;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#101;&amp;#120;&amp;#099;&amp;#104;&amp;#032;&amp;#097;&amp;#032;&amp;#105;&amp;#032;&amp;#114;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#100;&amp;#111;&amp;#032;&amp;#116;&amp;#109;&amp;#112;&amp;#105;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#032;&amp;#105;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#116;&amp;#109;&amp;#112;&amp;#114;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#032;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#119;&amp;#114;&amp;#105;&amp;#116;&amp;#101;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#032;&amp;#105;&amp;#032;&amp;#116;&amp;#109;&amp;#112;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#119;&amp;#114;&amp;#105;&amp;#116;&amp;#101;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#032;&amp;#105;&amp;#032;&amp;#116;&amp;#109;&amp;#112;&amp;#105;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#097;&amp;#032;&amp;#098;&amp;#032;&amp;#099;&amp;#032;&amp;#061;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#099;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#097;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#098;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#113;&amp;#117;&amp;#105;&amp;#099;&amp;#107;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#108;&amp;#032;&amp;#114;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#114;&amp;#032;&amp;#060;&amp;#061;&amp;#032;&amp;#108;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#040;&amp;#041;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#040;&amp;#108;&amp;#045;&amp;#049;&amp;#041;&amp;#032;&amp;#114;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#120;&amp;#099;&amp;#104;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#032;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#119;&amp;#105;&amp;#116;&amp;#104;&amp;#083;&amp;#116;&amp;#114;&amp;#097;&amp;#116;&amp;#101;&amp;#103;&amp;#121;&amp;#032;&amp;#114;&amp;#112;&amp;#097;&amp;#114;&amp;#032;&amp;#036;&amp;#032;&amp;#113;&amp;#117;&amp;#105;&amp;#099;&amp;#107;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#108;&amp;#032;&amp;#040;&amp;#105;&amp;#045;&amp;#049;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#113;&amp;#117;&amp;#105;&amp;#099;&amp;#107;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#040;&amp;#105;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#104;&amp;#101;&amp;#114;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#105;&amp;#032;&amp;#106;&amp;#032;&amp;#118;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#040;&amp;#105;&amp;#039;&amp;#044;&amp;#032;&amp;#106;&amp;#039;&amp;#041;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#108;&amp;#105;&amp;#102;&amp;#116;&amp;#077;&amp;#050;&amp;#032;&amp;#040;&amp;#044;&amp;#041;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#040;&amp;#062;&amp;#061;&amp;#118;&amp;#041;&amp;#032;&amp;#040;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#105;&amp;#043;&amp;#049;&amp;#041;&amp;#041;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#040;&amp;#060;&amp;#061;&amp;#118;&amp;#041;&amp;#032;&amp;#040;&amp;#115;&amp;#117;&amp;#098;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#106;&amp;#045;&amp;#049;&amp;#041;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#040;&amp;#105;&amp;#039;&amp;#032;&amp;#060;&amp;#032;&amp;#106;&amp;#039;&amp;#041;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#101;&amp;#120;&amp;#099;&amp;#104;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#039;&amp;#032;&amp;#106;&amp;#039;&amp;#032;&amp;#062;&amp;#062;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#105;&amp;#039;&amp;#032;&amp;#106;&amp;#039;&amp;#032;&amp;#118;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#105;&amp;#039;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#112;&amp;#032;&amp;#102;&amp;#032;&amp;#105;&amp;#032;&amp;#061;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#105;&amp;#032;&amp;#061;&amp;#061;&amp;#032;&amp;#108;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#105;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#105;&amp;#041;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#112;&amp;#032;&amp;#102;&amp;#032;&amp;#040;&amp;#102;&amp;#032;&amp;#105;&amp;#041;&amp;#041;&amp;#032;&amp;#046;&amp;#032;&amp;#112;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#061;&amp;#032;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#100;&amp;#111;&amp;#032;&amp;#091;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#093;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#102;&amp;#109;&amp;#097;&amp;#112;&amp;#032;&amp;#040;&amp;#102;&amp;#109;&amp;#097;&amp;#112;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#041;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#065;&amp;#114;&amp;#103;&amp;#115;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#080;&amp;#097;&amp;#114;&amp;#032;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#097;&amp;#110;&amp;#115;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#032;&amp;#040;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#032;&amp;#096;&amp;#100;&amp;#105;&amp;#118;&amp;#096;&amp;#032;&amp;#050;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&amp;#032;&amp;#097;&amp;#110;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#080;&amp;#097;&amp;#114;&amp;#032;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#032;&amp;#061;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#100;&amp;#111;&amp;#032;&amp;#120;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#113;&amp;#117;&amp;#105;&amp;#099;&amp;#107;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#120;&amp;#032;&amp;#048;&amp;#032;&amp;#040;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#120;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#058;&amp;#058;&amp;#032;&amp;#073;&amp;#110;&amp;#116;&amp;#032;&amp;#045;&amp;#062;&amp;#032;&amp;#073;&amp;#079;&amp;#032;&amp;#040;&amp;#073;&amp;#079;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#073;&amp;#110;&amp;#116;&amp;#032;&amp;#068;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#041;&amp;#013;&amp;#010;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#032;&amp;#061;&amp;#032;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#100;&amp;#111;&amp;#032;&amp;#097;&amp;#110;&amp;#115;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#110;&amp;#101;&amp;#119;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#040;&amp;#048;&amp;#044;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#045;&amp;#049;&amp;#041;&amp;#032;&amp;#091;&amp;#102;&amp;#114;&amp;#111;&amp;#109;&amp;#073;&amp;#110;&amp;#116;&amp;#101;&amp;#103;&amp;#114;&amp;#097;&amp;#108;&amp;#032;&amp;#036;&amp;#032;&amp;#072;&amp;#046;&amp;#104;&amp;#097;&amp;#115;&amp;#104;&amp;#083;&amp;#116;&amp;#114;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#036;&amp;#032;&amp;#115;&amp;#104;&amp;#111;&amp;#119;&amp;#032;&amp;#105;&amp;#032;&amp;#124;&amp;#032;&amp;#105;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#091;&amp;#049;&amp;#046;&amp;#046;&amp;#116;&amp;#101;&amp;#115;&amp;#116;&amp;#083;&amp;#105;&amp;#122;&amp;#101;&amp;#093;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#097;&amp;#110;&amp;#115;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;This solution uses &lt;a href="http://hackage.haskell.org/packages/archive/parallel/2.2.0.1/doc/html/Control-Parallel-Strategies.html"&gt;Haskell's parallel "strategies"&lt;/a&gt;. This concept was introduced to give Haskell programmers more control over parallelization but &lt;a href="http://www.haskell.org/~simonmar/papers/multicore-ghc.pdf"&gt;the only available implementation was found to leak memory&lt;/a&gt; and nobody was able to get it to work in this case: Jim's solution contains a concurrency bug that causes it to return incorrect results almost every time it is called.&lt;/p&gt;&lt;p&gt;Peaker then posted &lt;a href="http://www.reddit.com/r/coding/comments/codqo/engineering_large_projects_in_a_functional/c0ur6yx"&gt;his own Haskell solution&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#046;&amp;#073;&amp;#079;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#067;&amp;#111;&amp;#110;&amp;#116;&amp;#114;&amp;#111;&amp;#108;&amp;#046;&amp;#077;&amp;#111;&amp;#110;&amp;#097;&amp;#100;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#067;&amp;#111;&amp;#110;&amp;#116;&amp;#114;&amp;#111;&amp;#108;&amp;#046;&amp;#067;&amp;#111;&amp;#110;&amp;#099;&amp;#117;&amp;#114;&amp;#114;&amp;#101;&amp;#110;&amp;#116;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#116;&amp;#032;&amp;#095;&amp;#102;&amp;#032;&amp;#084;&amp;#114;&amp;#117;&amp;#101;&amp;#032;&amp;#061;&amp;#032;&amp;#116;&amp;#013;&amp;#010;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#095;&amp;#116;&amp;#032;&amp;#102;&amp;#032;&amp;#070;&amp;#097;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#061;&amp;#032;&amp;#102;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#032;&amp;#106;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#040;&amp;#105;&amp;#118;&amp;#044;&amp;#032;&amp;#106;&amp;#118;&amp;#041;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#108;&amp;#105;&amp;#102;&amp;#116;&amp;#077;&amp;#050;&amp;#032;&amp;#040;&amp;#044;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#106;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#114;&amp;#105;&amp;#116;&amp;#101;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#032;&amp;#106;&amp;#118;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#114;&amp;#105;&amp;#116;&amp;#101;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#106;&amp;#032;&amp;#105;&amp;#118;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#112;&amp;#097;&amp;#114;&amp;#097;&amp;#108;&amp;#108;&amp;#101;&amp;#108;&amp;#032;&amp;#102;&amp;#103;&amp;#032;&amp;#098;&amp;#103;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#109;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#110;&amp;#101;&amp;#119;&amp;#069;&amp;#109;&amp;#112;&amp;#116;&amp;#121;&amp;#077;&amp;#086;&amp;#097;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#102;&amp;#111;&amp;#114;&amp;#107;&amp;#073;&amp;#079;&amp;#032;&amp;#040;&amp;#098;&amp;#103;&amp;#032;&amp;#062;&amp;#062;&amp;#032;&amp;#112;&amp;#117;&amp;#116;&amp;#077;&amp;#086;&amp;#097;&amp;#114;&amp;#032;&amp;#109;&amp;#032;&amp;#040;&amp;#041;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#102;&amp;#103;&amp;#032;&amp;#062;&amp;#062;&amp;#032;&amp;#116;&amp;#097;&amp;#107;&amp;#101;&amp;#077;&amp;#086;&amp;#097;&amp;#114;&amp;#032;&amp;#109;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#119;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#040;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#060;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#041;&amp;#032;&amp;#036;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#040;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#104;&amp;#101;&amp;#114;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#061;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#119;&amp;#032;&amp;#061;&amp;#032;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#110;&amp;#032;&amp;#112;&amp;#114;&amp;#101;&amp;#100;&amp;#032;&amp;#105;&amp;#032;&amp;#061;&amp;#032;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#110;&amp;#032;&amp;#112;&amp;#114;&amp;#101;&amp;#100;&amp;#032;&amp;#040;&amp;#110;&amp;#032;&amp;#105;&amp;#041;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#105;&amp;#041;&amp;#032;&amp;#046;&amp;#032;&amp;#112;&amp;#114;&amp;#101;&amp;#100;&amp;#032;&amp;#105;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#105;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#118;&amp;#101;&amp;#032;&amp;#111;&amp;#112;&amp;#032;&amp;#100;&amp;#032;&amp;#105;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#111;&amp;#112;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#040;&amp;#115;&amp;#119;&amp;#032;&amp;#040;&amp;#100;&amp;#032;&amp;#111;&amp;#112;&amp;#041;&amp;#032;&amp;#105;&amp;#032;&amp;#062;&amp;#062;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#040;&amp;#100;&amp;#032;&amp;#111;&amp;#112;&amp;#041;&amp;#041;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#105;&amp;#102;&amp;#116;&amp;#077;&amp;#032;&amp;#040;&amp;#047;&amp;#061;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#105;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#111;&amp;#105;&amp;#032;&amp;#111;&amp;#106;&amp;#032;&amp;#111;&amp;#112;&amp;#032;&amp;#111;&amp;#113;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#040;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#099;&amp;#111;&amp;#110;&amp;#115;&amp;#116;&amp;#032;&amp;#040;&amp;#060;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#041;&amp;#041;&amp;#032;&amp;#111;&amp;#105;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#106;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#040;&amp;#115;&amp;#117;&amp;#098;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#092;&amp;#105;&amp;#100;&amp;#120;&amp;#032;&amp;#099;&amp;#101;&amp;#108;&amp;#108;&amp;#032;&amp;#045;&amp;#062;&amp;#032;&amp;#099;&amp;#101;&amp;#108;&amp;#108;&amp;#062;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#038;&amp;#038;&amp;#032;&amp;#105;&amp;#100;&amp;#120;&amp;#047;&amp;#061;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#041;&amp;#032;&amp;#111;&amp;#106;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#105;&amp;#032;&amp;#060;&amp;#032;&amp;#106;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#119;&amp;#032;&amp;#105;&amp;#032;&amp;#106;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#112;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#109;&amp;#111;&amp;#118;&amp;#101;&amp;#032;&amp;#111;&amp;#112;&amp;#032;&amp;#040;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#105;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#113;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#109;&amp;#111;&amp;#118;&amp;#101;&amp;#032;&amp;#111;&amp;#113;&amp;#032;&amp;#040;&amp;#115;&amp;#117;&amp;#098;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#106;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#040;&amp;#105;&amp;#032;&amp;#043;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#106;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#112;&amp;#032;&amp;#113;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#119;&amp;#032;&amp;#105;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#111;&amp;#114;&amp;#077;&amp;#095;&amp;#032;&amp;#040;&amp;#122;&amp;#105;&amp;#112;&amp;#032;&amp;#091;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#046;&amp;#046;&amp;#111;&amp;#112;&amp;#045;&amp;#049;&amp;#093;&amp;#032;&amp;#091;&amp;#105;&amp;#045;&amp;#049;&amp;#044;&amp;#105;&amp;#045;&amp;#050;&amp;#046;&amp;#046;&amp;#093;&amp;#041;&amp;#032;&amp;#036;&amp;#032;&amp;#117;&amp;#110;&amp;#099;&amp;#117;&amp;#114;&amp;#114;&amp;#121;&amp;#032;&amp;#115;&amp;#119;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#111;&amp;#114;&amp;#077;&amp;#095;&amp;#032;&amp;#040;&amp;#122;&amp;#105;&amp;#112;&amp;#032;&amp;#091;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#045;&amp;#049;&amp;#044;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#045;&amp;#050;&amp;#046;&amp;#046;&amp;#111;&amp;#113;&amp;#043;&amp;#049;&amp;#093;&amp;#032;&amp;#091;&amp;#105;&amp;#043;&amp;#049;&amp;#046;&amp;#046;&amp;#093;&amp;#041;&amp;#032;&amp;#036;&amp;#032;&amp;#117;&amp;#110;&amp;#099;&amp;#117;&amp;#114;&amp;#114;&amp;#121;&amp;#032;&amp;#115;&amp;#119;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#110;&amp;#105;&amp;#032;&amp;#061;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#062;&amp;#061;&amp;#032;&amp;#111;&amp;#112;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#105;&amp;#032;&amp;#043;&amp;#032;&amp;#049;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#032;&amp;#043;&amp;#032;&amp;#105;&amp;#032;&amp;#045;&amp;#032;&amp;#111;&amp;#113;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#110;&amp;#106;&amp;#032;&amp;#061;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#045;&amp;#049;&amp;#032;&amp;#060;&amp;#061;&amp;#032;&amp;#111;&amp;#113;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#105;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#043;&amp;#032;&amp;#105;&amp;#032;&amp;#045;&amp;#032;&amp;#111;&amp;#112;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#115;&amp;#104;&amp;#032;&amp;#061;&amp;#032;&amp;#049;&amp;#048;&amp;#050;&amp;#052;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#116;&amp;#114;&amp;#097;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#110;&amp;#106;&amp;#032;&amp;#045;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#060;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#115;&amp;#104;&amp;#032;&amp;#124;&amp;#124;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#032;&amp;#045;&amp;#032;&amp;#110;&amp;#105;&amp;#032;&amp;#060;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#115;&amp;#104;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#040;&amp;#062;&amp;#062;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#112;&amp;#097;&amp;#114;&amp;#097;&amp;#108;&amp;#108;&amp;#101;&amp;#108;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#110;&amp;#106;&amp;#032;&amp;#096;&amp;#115;&amp;#116;&amp;#114;&amp;#097;&amp;#116;&amp;#096;&amp;#032;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#110;&amp;#105;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#110;&amp;#101;&amp;#119;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#040;&amp;#048;&amp;#044;&amp;#032;&amp;#053;&amp;#041;&amp;#032;&amp;#091;&amp;#051;&amp;#044;&amp;#049;&amp;#044;&amp;#055;&amp;#044;&amp;#050;&amp;#044;&amp;#052;&amp;#044;&amp;#056;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#069;&amp;#108;&amp;#101;&amp;#109;&amp;#115;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#058;&amp;#058;&amp;#032;&amp;#073;&amp;#079;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#073;&amp;#110;&amp;#116;&amp;#032;&amp;#073;&amp;#110;&amp;#116;&amp;#041;&amp;#032;&amp;#048;&amp;#032;&amp;#053;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#069;&amp;#108;&amp;#101;&amp;#109;&amp;#115;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;This solution also turned out to be buggy. Firstly, it contains a more subtle concurrency bug causes it to return incorrect results only occassionally. Peaker &lt;a href="http://www.reddit.com/r/coding/comments/codqo/engineering_large_projects_in_a_functional/c0v1bw5"&gt;corrected this bug to give the following code&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#084;&amp;#105;&amp;#109;&amp;#101;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#082;&amp;#097;&amp;#110;&amp;#100;&amp;#111;&amp;#109;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#046;&amp;#073;&amp;#079;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#067;&amp;#111;&amp;#110;&amp;#116;&amp;#114;&amp;#111;&amp;#108;&amp;#046;&amp;#077;&amp;#111;&amp;#110;&amp;#097;&amp;#100;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#067;&amp;#111;&amp;#110;&amp;#116;&amp;#114;&amp;#111;&amp;#108;&amp;#046;&amp;#067;&amp;#111;&amp;#110;&amp;#099;&amp;#117;&amp;#114;&amp;#114;&amp;#101;&amp;#110;&amp;#116;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#067;&amp;#111;&amp;#110;&amp;#116;&amp;#114;&amp;#111;&amp;#108;&amp;#046;&amp;#069;&amp;#120;&amp;#099;&amp;#101;&amp;#112;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#013;&amp;#010;&amp;#105;&amp;#109;&amp;#112;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#113;&amp;#117;&amp;#097;&amp;#108;&amp;#105;&amp;#102;&amp;#105;&amp;#101;&amp;#100;&amp;#032;&amp;#068;&amp;#097;&amp;#116;&amp;#097;&amp;#046;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#032;&amp;#097;&amp;#115;&amp;#032;&amp;#076;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#116;&amp;#032;&amp;#095;&amp;#032;&amp;#084;&amp;#114;&amp;#117;&amp;#101;&amp;#032;&amp;#061;&amp;#032;&amp;#116;&amp;#013;&amp;#010;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#095;&amp;#032;&amp;#102;&amp;#032;&amp;#070;&amp;#097;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#061;&amp;#032;&amp;#102;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#032;&amp;#106;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#040;&amp;#105;&amp;#118;&amp;#044;&amp;#032;&amp;#106;&amp;#118;&amp;#041;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#108;&amp;#105;&amp;#102;&amp;#116;&amp;#077;&amp;#050;&amp;#032;&amp;#040;&amp;#044;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#106;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#114;&amp;#105;&amp;#116;&amp;#101;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#105;&amp;#032;&amp;#106;&amp;#118;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#114;&amp;#105;&amp;#116;&amp;#101;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#106;&amp;#032;&amp;#105;&amp;#118;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#098;&amp;#097;&amp;#099;&amp;#107;&amp;#103;&amp;#114;&amp;#111;&amp;#117;&amp;#110;&amp;#100;&amp;#032;&amp;#116;&amp;#097;&amp;#115;&amp;#107;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#109;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#110;&amp;#101;&amp;#119;&amp;#069;&amp;#109;&amp;#112;&amp;#116;&amp;#121;&amp;#077;&amp;#086;&amp;#097;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#102;&amp;#111;&amp;#114;&amp;#107;&amp;#073;&amp;#079;&amp;#032;&amp;#040;&amp;#116;&amp;#097;&amp;#115;&amp;#107;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#112;&amp;#117;&amp;#116;&amp;#077;&amp;#086;&amp;#097;&amp;#114;&amp;#032;&amp;#109;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#036;&amp;#032;&amp;#116;&amp;#097;&amp;#107;&amp;#101;&amp;#077;&amp;#086;&amp;#097;&amp;#114;&amp;#032;&amp;#109;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#112;&amp;#097;&amp;#114;&amp;#097;&amp;#108;&amp;#108;&amp;#101;&amp;#108;&amp;#032;&amp;#102;&amp;#103;&amp;#032;&amp;#098;&amp;#103;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#097;&amp;#105;&amp;#116;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#098;&amp;#097;&amp;#099;&amp;#107;&amp;#103;&amp;#114;&amp;#111;&amp;#117;&amp;#110;&amp;#100;&amp;#032;&amp;#098;&amp;#103;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#102;&amp;#103;&amp;#032;&amp;#062;&amp;#062;&amp;#032;&amp;#119;&amp;#097;&amp;#105;&amp;#116;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#119;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#040;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#060;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#041;&amp;#032;&amp;#036;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#040;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#119;&amp;#104;&amp;#101;&amp;#114;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#061;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#119;&amp;#032;&amp;#061;&amp;#032;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#110;&amp;#032;&amp;#112;&amp;#114;&amp;#101;&amp;#100;&amp;#032;&amp;#105;&amp;#032;&amp;#061;&amp;#032;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#040;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#110;&amp;#032;&amp;#112;&amp;#114;&amp;#101;&amp;#100;&amp;#032;&amp;#040;&amp;#110;&amp;#032;&amp;#105;&amp;#041;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#105;&amp;#041;&amp;#032;&amp;#046;&amp;#032;&amp;#112;&amp;#114;&amp;#101;&amp;#100;&amp;#032;&amp;#105;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#032;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#105;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#111;&amp;#118;&amp;#101;&amp;#032;&amp;#111;&amp;#112;&amp;#032;&amp;#100;&amp;#032;&amp;#105;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#098;&amp;#111;&amp;#111;&amp;#108;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#111;&amp;#112;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#040;&amp;#115;&amp;#119;&amp;#032;&amp;#040;&amp;#100;&amp;#032;&amp;#111;&amp;#112;&amp;#041;&amp;#032;&amp;#105;&amp;#032;&amp;#062;&amp;#062;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#040;&amp;#100;&amp;#032;&amp;#111;&amp;#112;&amp;#041;&amp;#041;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#105;&amp;#102;&amp;#116;&amp;#077;&amp;#032;&amp;#040;&amp;#047;&amp;#061;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#101;&amp;#097;&amp;#100;&amp;#032;&amp;#105;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#082;&amp;#097;&amp;#110;&amp;#103;&amp;#101;&amp;#032;&amp;#112;&amp;#120;&amp;#032;&amp;#120;&amp;#032;&amp;#110;&amp;#120;&amp;#032;&amp;#121;&amp;#032;&amp;#110;&amp;#121;&amp;#032;&amp;#061;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#112;&amp;#120;&amp;#032;&amp;#120;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#115;&amp;#119;&amp;#032;&amp;#120;&amp;#032;&amp;#121;&amp;#032;&amp;#062;&amp;#062;&amp;#032;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#082;&amp;#097;&amp;#110;&amp;#103;&amp;#101;&amp;#032;&amp;#112;&amp;#120;&amp;#032;&amp;#040;&amp;#110;&amp;#120;&amp;#032;&amp;#120;&amp;#041;&amp;#032;&amp;#110;&amp;#120;&amp;#032;&amp;#040;&amp;#110;&amp;#121;&amp;#032;&amp;#121;&amp;#041;&amp;#032;&amp;#110;&amp;#121;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#121;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#111;&amp;#105;&amp;#032;&amp;#111;&amp;#106;&amp;#032;&amp;#111;&amp;#112;&amp;#032;&amp;#111;&amp;#113;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#040;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#099;&amp;#111;&amp;#110;&amp;#115;&amp;#116;&amp;#032;&amp;#040;&amp;#060;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#041;&amp;#041;&amp;#032;&amp;#111;&amp;#105;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#106;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#102;&amp;#105;&amp;#110;&amp;#100;&amp;#032;&amp;#040;&amp;#115;&amp;#117;&amp;#098;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#092;&amp;#105;&amp;#100;&amp;#120;&amp;#032;&amp;#099;&amp;#101;&amp;#108;&amp;#108;&amp;#032;&amp;#045;&amp;#062;&amp;#032;&amp;#099;&amp;#101;&amp;#108;&amp;#108;&amp;#062;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#038;&amp;#038;&amp;#032;&amp;#105;&amp;#100;&amp;#120;&amp;#047;&amp;#061;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#041;&amp;#032;&amp;#111;&amp;#106;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#105;&amp;#032;&amp;#060;&amp;#032;&amp;#106;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#119;&amp;#032;&amp;#105;&amp;#032;&amp;#106;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#112;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#109;&amp;#111;&amp;#118;&amp;#101;&amp;#032;&amp;#111;&amp;#112;&amp;#032;&amp;#040;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#105;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#113;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#109;&amp;#111;&amp;#118;&amp;#101;&amp;#032;&amp;#111;&amp;#113;&amp;#032;&amp;#040;&amp;#115;&amp;#117;&amp;#098;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#106;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#111;&amp;#111;&amp;#112;&amp;#032;&amp;#112;&amp;#105;&amp;#118;&amp;#111;&amp;#116;&amp;#032;&amp;#040;&amp;#105;&amp;#032;&amp;#043;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#106;&amp;#032;&amp;#045;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#112;&amp;#032;&amp;#113;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#119;&amp;#032;&amp;#105;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#110;&amp;#106;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#082;&amp;#097;&amp;#110;&amp;#103;&amp;#101;&amp;#032;&amp;#040;&amp;#060;&amp;#111;&amp;#112;&amp;#041;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#040;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#105;&amp;#045;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#115;&amp;#117;&amp;#098;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#049;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#110;&amp;#105;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#115;&amp;#119;&amp;#097;&amp;#112;&amp;#082;&amp;#097;&amp;#110;&amp;#103;&amp;#101;&amp;#032;&amp;#040;&amp;#062;&amp;#111;&amp;#113;&amp;#041;&amp;#032;&amp;#040;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#045;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#115;&amp;#117;&amp;#098;&amp;#116;&amp;#114;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#105;&amp;#043;&amp;#049;&amp;#041;&amp;#032;&amp;#040;&amp;#043;&amp;#049;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#115;&amp;#104;&amp;#032;&amp;#061;&amp;#032;&amp;#049;&amp;#048;&amp;#050;&amp;#052;&amp;#048;&amp;#048;&amp;#048;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#116;&amp;#114;&amp;#097;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#105;&amp;#102;&amp;#032;&amp;#110;&amp;#106;&amp;#032;&amp;#045;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#060;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#115;&amp;#104;&amp;#032;&amp;#124;&amp;#124;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#032;&amp;#045;&amp;#032;&amp;#110;&amp;#105;&amp;#032;&amp;#060;&amp;#032;&amp;#116;&amp;#104;&amp;#114;&amp;#101;&amp;#115;&amp;#104;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#116;&amp;#104;&amp;#101;&amp;#110;&amp;#032;&amp;#040;&amp;#062;&amp;#062;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#115;&amp;#101;&amp;#032;&amp;#112;&amp;#097;&amp;#114;&amp;#097;&amp;#108;&amp;#108;&amp;#101;&amp;#108;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#108;&amp;#101;&amp;#102;&amp;#116;&amp;#032;&amp;#110;&amp;#106;&amp;#032;&amp;#096;&amp;#115;&amp;#116;&amp;#114;&amp;#097;&amp;#116;&amp;#096;&amp;#032;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#110;&amp;#105;&amp;#032;&amp;#114;&amp;#105;&amp;#103;&amp;#104;&amp;#116;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#100;&amp;#032;&amp;#097;&amp;#099;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#084;&amp;#079;&amp;#068;&amp;#032;&amp;#098;&amp;#101;&amp;#102;&amp;#111;&amp;#114;&amp;#101;&amp;#083;&amp;#101;&amp;#099;&amp;#032;&amp;#098;&amp;#101;&amp;#102;&amp;#111;&amp;#114;&amp;#101;&amp;#085;&amp;#083;&amp;#101;&amp;#099;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#067;&amp;#108;&amp;#111;&amp;#099;&amp;#107;&amp;#084;&amp;#105;&amp;#109;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#120;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#097;&amp;#099;&amp;#116;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#084;&amp;#079;&amp;#068;&amp;#032;&amp;#097;&amp;#102;&amp;#116;&amp;#101;&amp;#114;&amp;#083;&amp;#101;&amp;#099;&amp;#032;&amp;#097;&amp;#102;&amp;#116;&amp;#101;&amp;#114;&amp;#085;&amp;#083;&amp;#101;&amp;#099;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#067;&amp;#108;&amp;#111;&amp;#099;&amp;#107;&amp;#084;&amp;#105;&amp;#109;&amp;#101;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#114;&amp;#101;&amp;#116;&amp;#117;&amp;#114;&amp;#110;&amp;#032;&amp;#040;&amp;#102;&amp;#114;&amp;#111;&amp;#109;&amp;#073;&amp;#110;&amp;#116;&amp;#101;&amp;#103;&amp;#114;&amp;#097;&amp;#108;&amp;#032;&amp;#040;&amp;#097;&amp;#102;&amp;#116;&amp;#101;&amp;#114;&amp;#083;&amp;#101;&amp;#099;&amp;#032;&amp;#045;&amp;#032;&amp;#098;&amp;#101;&amp;#102;&amp;#111;&amp;#114;&amp;#101;&amp;#083;&amp;#101;&amp;#099;&amp;#041;&amp;#032;&amp;#043;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#102;&amp;#114;&amp;#111;&amp;#109;&amp;#073;&amp;#110;&amp;#116;&amp;#101;&amp;#103;&amp;#114;&amp;#097;&amp;#108;&amp;#032;&amp;#040;&amp;#097;&amp;#102;&amp;#116;&amp;#101;&amp;#114;&amp;#085;&amp;#083;&amp;#101;&amp;#099;&amp;#032;&amp;#045;&amp;#032;&amp;#098;&amp;#101;&amp;#102;&amp;#111;&amp;#114;&amp;#101;&amp;#085;&amp;#083;&amp;#101;&amp;#099;&amp;#041;&amp;#032;&amp;#047;&amp;#032;&amp;#049;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#044;&amp;#032;&amp;#120;&amp;#041;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#032;&amp;#061;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#110;&amp;#032;&amp;#061;&amp;#032;&amp;#049;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#117;&amp;#116;&amp;#083;&amp;#116;&amp;#114;&amp;#076;&amp;#110;&amp;#032;&amp;#034;&amp;#077;&amp;#097;&amp;#107;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#114;&amp;#097;&amp;#110;&amp;#100;&amp;#115;&amp;#034;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#110;&amp;#101;&amp;#119;&amp;#076;&amp;#105;&amp;#115;&amp;#116;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#040;&amp;#048;&amp;#044;&amp;#032;&amp;#110;&amp;#045;&amp;#049;&amp;#041;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#032;&amp;#114;&amp;#101;&amp;#112;&amp;#108;&amp;#105;&amp;#099;&amp;#097;&amp;#116;&amp;#101;&amp;#077;&amp;#032;&amp;#110;&amp;#032;&amp;#040;&amp;#114;&amp;#097;&amp;#110;&amp;#100;&amp;#111;&amp;#109;&amp;#082;&amp;#073;&amp;#079;&amp;#032;&amp;#040;&amp;#048;&amp;#044;&amp;#032;&amp;#049;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#041;&amp;#032;&amp;#062;&amp;#062;&amp;#061;&amp;#032;&amp;#101;&amp;#118;&amp;#097;&amp;#108;&amp;#117;&amp;#097;&amp;#116;&amp;#101;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#101;&amp;#108;&amp;#101;&amp;#109;&amp;#115;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#069;&amp;#108;&amp;#101;&amp;#109;&amp;#115;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#117;&amp;#116;&amp;#083;&amp;#116;&amp;#114;&amp;#076;&amp;#110;&amp;#032;&amp;#034;&amp;#078;&amp;#111;&amp;#119;&amp;#032;&amp;#115;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#034;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#040;&amp;#116;&amp;#105;&amp;#109;&amp;#105;&amp;#110;&amp;#103;&amp;#044;&amp;#032;&amp;#095;&amp;#041;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#116;&amp;#105;&amp;#109;&amp;#101;&amp;#100;&amp;#032;&amp;#036;&amp;#032;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#040;&amp;#097;&amp;#114;&amp;#114;&amp;#032;&amp;#058;&amp;#058;&amp;#032;&amp;#073;&amp;#079;&amp;#065;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#032;&amp;#073;&amp;#110;&amp;#116;&amp;#032;&amp;#073;&amp;#110;&amp;#116;&amp;#041;&amp;#032;&amp;#048;&amp;#032;&amp;#040;&amp;#110;&amp;#045;&amp;#049;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&amp;#032;&amp;#046;&amp;#032;&amp;#040;&amp;#076;&amp;#046;&amp;#115;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#101;&amp;#108;&amp;#101;&amp;#109;&amp;#115;&amp;#032;&amp;#061;&amp;#061;&amp;#041;&amp;#032;&amp;#061;&amp;#060;&amp;#060;&amp;#032;&amp;#103;&amp;#101;&amp;#116;&amp;#069;&amp;#108;&amp;#101;&amp;#109;&amp;#115;&amp;#032;&amp;#097;&amp;#114;&amp;#114;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#117;&amp;#116;&amp;#083;&amp;#116;&amp;#114;&amp;#076;&amp;#110;&amp;#032;&amp;#036;&amp;#032;&amp;#034;&amp;#083;&amp;#111;&amp;#114;&amp;#116;&amp;#032;&amp;#116;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#034;&amp;#032;&amp;#043;&amp;#043;&amp;#032;&amp;#115;&amp;#104;&amp;#111;&amp;#119;&amp;#032;&amp;#116;&amp;#105;&amp;#109;&amp;#105;&amp;#110;&amp;#103;&amp;#032;&amp;#043;&amp;#043;&amp;#032;&amp;#034;&amp;#032;&amp;#115;&amp;#101;&amp;#099;&amp;#111;&amp;#110;&amp;#100;&amp;#115;&amp;#034;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;This solution does run correctly on small inputs but increasing the problem size to 1,000,000 elements results in a stack overflow. Two attempts were made to diagnose this bug, &lt;a href="http://www.reddit.com/r/coding/comments/codqo/engineering_large_projects_in_a_functional/c0v182l"&gt;here&lt;/a&gt; and &lt;a href="http://www.reddit.com/r/programming/comments/bnnoh/fast_automatically_parallel_arrays_for_haskell/c0vm0w7"&gt;here&lt;/a&gt;, but both turned out to be wrong. The &lt;a href="http://www.reddit.com/r/programming/comments/bnnoh/fast_automatically_parallel_arrays_for_haskell/c0vpw9b"&gt;bug&lt;/a&gt; is actually in the &lt;span style="font-family:courier new;"&gt;&lt;a href="http://haskell.org/ghc/docs/6.12.1/html/libraries/array-0.3.0.0/Data-Array-MArray.html#v%3AgetElems"&gt;getElems&lt;/a&gt;&lt;/span&gt; function of the Haskell standard library which stack overflows on long arrays.&lt;/p&gt;&lt;p&gt;Surprisingly, more bug fixing seems to have culminated in the world's first parallel generic quicksort written in Haskell. Furthermore, the resulting Haskell solution is only around 55% slower than the equivalent F# solution. Note that this requires the latest GHC that was only released in recent weeks.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-6673296700767162245?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/6673296700767162245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=6673296700767162245' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6673296700767162245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6673296700767162245'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/08/parallel-generic-quicksort-in-haskell.html' title='Parallel generic quicksort in Haskell'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-6083823845845448794</id><published>2010-08-01T05:39:00.000-07:00</published><updated>2010-08-01T06:32:03.472-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='ocaml for scientists'/><category scheme='http://www.blogger.com/atom/ns#' term='ocaml journal'/><title type='text'>The rise and fall of OCaml</title><content type='html'>&lt;p&gt;After over 3 years, &lt;a href="http://www.ffconsultancy.com/products/ocaml_journal/?ffb"&gt;The OCaml Journal&lt;/a&gt; is finally closing down. New subscriptions offer access to the 75 existing articles and only a few more articles will be published, to honour outstanding subscriptions.&lt;/p&gt;&lt;p&gt;This marks &lt;a href="http://www.ffconsultancy.com/"&gt;Flying Frog Consultancy Ltd.&lt;/a&gt; officially pulling out of the OCaml market as our remaining OCaml products (such as the &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/?ffb"&gt;OCaml for Scientists&lt;/a&gt; book) require no on-going maintenance.&lt;/p&gt;&lt;p&gt;This change has, of course, come about due to a dramatic fall in our revenue from OCaml products since 2007. This is partly because we decided in 2007 to jump ship to Microsoft's new &lt;a href="http://www.ffconsultancy.com/products/fsharp_for_technical_computing/?ffb"&gt;F# programming language&lt;/a&gt;. However, the same trend can be seen in the rate of posts to the OCaml mailing lists, which has fallen 60% since 2007 and has now reached its lowest level for a decade:&lt;/p&gt;&lt;a href="http://3.bp.blogspot.com/_NMRkpon4Ps0/TFVthFI3KsI/AAAAAAAAAJQ/bZe2GtRNHxI/s1600/OCamlListTraffic.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 247px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5500422934985386690" border="0" alt="" src="http://3.bp.blogspot.com/_NMRkpon4Ps0/TFVthFI3KsI/AAAAAAAAAJQ/bZe2GtRNHxI/s400/OCamlListTraffic.png" /&gt;&lt;/a&gt; &lt;p&gt;We blame the inability of OCaml's garbage collector to allow threads to run in parallel as the primary reason for this mass exodus. OCaml was an awesome tool in the late 1990s and, by 2004, many people were finding the OCaml language from benchmark results that showed it to be one of the fastest languages available. Ironically, that was largely due to the superior performance of OCaml's garbage collector but that same garbage collector is now a serious impediment to parallel programming on today's multicore machines. Coupled with advancements like monomorphization on .NET and LLVM-based backends with vastly better code generation like GHC, OCaml has been left in the dust. Consequently, the majority of OCaml programmers who had chosen it for performance reasons (many of whom were research scientists) are leaving.&lt;/p&gt;&lt;p&gt;OCaml also suffers from several other problems including the cumbersome FFI that requires separate C stubs and the lack of a native-code REPL. However, all of these problems could be addressed by developing a new VM. Indeed, at only 2kLOC &lt;a href="http://www.ffconsultancy.com/ocaml/hlvm/?ffb"&gt;our own HLVM project&lt;/a&gt; has demonstrated just how easy LLVM makes it to build a new &lt;a href="http://flyingfrogblog.blogspot.com/2009/03/performance-ocaml-vs-hlvm-beta-04.html"&gt;high-performance&lt;/a&gt; &lt;a href="http://flyingfrogblog.blogspot.com/2010/01/naive-parallelism-with-hlvm.html"&gt;multicore-capable&lt;/a&gt; VM for OCaml-like languages. We believe a complete replacement could be developed in just a few months but, sadly, nobody has done any work on this beyond our own tentative attempts with HLVM.&lt;/p&gt;&lt;p&gt;On the other hand, there was never any onus on an academic institution to create such a useful tool in the first place so it is important to remember that OCaml was only valuable thanks to the hard work and dedication of its academic creators. Thanks INRIA!&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-6083823845845448794?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/6083823845845448794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=6083823845845448794' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6083823845845448794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6083823845845448794'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/08/rise-and-fall-of-ocaml.html' title='The rise and fall of OCaml'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_NMRkpon4Ps0/TFVthFI3KsI/AAAAAAAAAJQ/bZe2GtRNHxI/s72-c/OCamlListTraffic.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-1620233404011990916</id><published>2010-07-31T12:25:00.001-07:00</published><updated>2010-07-31T13:05:35.608-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ParallelTable'/><category scheme='http://www.blogger.com/atom/ns#' term='MinCut'/><category scheme='http://www.blogger.com/atom/ns#' term='bugs'/><category scheme='http://www.blogger.com/atom/ns#' term='regular expression'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematica'/><title type='text'>Mathematica 7 review: buggy but fun!</title><content type='html'>&lt;p&gt;At only £195+VAT, the &lt;a href="http://www.wolfram.com/products/mathematicahomeedition/"&gt;Mathematica 7 Home Edition&lt;/a&gt; is just too tempting as an executive toy but it still seems to be far too buggy to be taken seriously. After just a few hours of playing around, a variety of bugs have become apparent. Every Mathematica user fears the dreaded error box that marks the loss of all unsaved data:&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79Q7B1pI/AAAAAAAAAIw/3xr1aDtO70I/s1600/Crash.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 216px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5500157337371006610" border="0" alt="" src="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79Q7B1pI/AAAAAAAAAIw/3xr1aDtO70I/s400/Crash.png" /&gt;&lt;/a&gt; &lt;p&gt;Fortunately, &lt;a href="http://flyingfrogblog.blogspot.com/2009/05/mathematica-bug-afflicting-our-product.html"&gt;a really serious bug in the FFT routines of Mathematica 7.0.0&lt;/a&gt; was fixed for the 7.0.1 release. This was a showstopper for customers of &lt;a href="http://www.ffconsultancy.com/products/CWT/?ffb"&gt;our time-frequency analysis add-on&lt;/a&gt;. The severity and ubiquity of this bug really highlights just how little quality assurance goes into Wolfram's software which, in turn, goes to show how a unimportant correctness is in the creation of commercially-successful software products, even if they are used in &lt;a href="http://www.wolfram.com/solutions/AerospaceEngineering/"&gt;aerospace engineering&lt;/a&gt;!&lt;/p&gt;&lt;p&gt;The first bug is in the new support for parallelism in Mathematica. Although it is only supposed to handle 4 cores, it produces &lt;a href="http://mathematicanews.blogspot.com/2010/07/all-pairs-shortest-paths.html"&gt;pages of errors&lt;/a&gt; when run on a machine with more cores such as our 8 core system:&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79O7WpDI/AAAAAAAAAIo/FfzNxyaxA90/s1600/AllPairsShortestPaths.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 270px; DISPLAY: block; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5500157336835499058" border="0" alt="" src="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79O7WpDI/AAAAAAAAAIo/FfzNxyaxA90/s400/AllPairsShortestPaths.png" /&gt;&lt;/a&gt; &lt;p&gt;Half of the spawned kernels die and the errors are about miscommunications. Looks like it was not tested on anything beyond a quadcore.&lt;/p&gt;&lt;p&gt;Another bug appears when trying to load the example matrices as described in Mathematica's own documentation:&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79iKsrUI/AAAAAAAAAI4/2Ep4KnWAtug/s1600/ExampleMatrixBug.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 90px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5500157342000131394" border="0" alt="" src="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79iKsrUI/AAAAAAAAAI4/2Ep4KnWAtug/s400/ExampleMatrixBug.png" /&gt;&lt;/a&gt; &lt;p&gt;And there seems to be a nasty bug in the &lt;span style="font-family:courier new;"&gt;MinCut&lt;/span&gt; function that is supposed to find partitions that break the fewest edges because this function causes an access violation (aka segmentation fault) every time we try to use it:&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79_3PUGI/AAAAAAAAAJA/GMH2uwXAHFw/s1600/MinCutBug.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 201px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5500157349971578978" border="0" alt="" src="http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79_3PUGI/AAAAAAAAAJA/GMH2uwXAHFw/s400/MinCutBug.png" /&gt;&lt;/a&gt; &lt;p&gt;A &lt;a href="http://stackoverflow.com/questions/2257884/bug-in-mathematica-regular-expression-applied-to-very-long-string"&gt;question on Stack Overflow&lt;/a&gt; highlighted another bug, this time in Mathematica's regular expression engine which crashes on non-trivial inputs, again losing all unsaved data:&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/_NMRkpon4Ps0/TFR7-eTi8AI/AAAAAAAAAJI/pew9_OchFg0/s1600/Regex.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 160px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5500157358143369218" border="0" alt="" src="http://2.bp.blogspot.com/_NMRkpon4Ps0/TFR7-eTi8AI/AAAAAAAAAJI/pew9_OchFg0/s400/Regex.png" /&gt;&lt;/a&gt; &lt;p&gt;So, although we do not hesitate to recommend Mathematica as an executive toy or even fun educational software for children, we still cannot recommend Mathematica for serious use due to the pervasiveness of serious bugs in this software. On the other hand, Mathematica's commercial success really demonstrates just how unimportant quality is in the software world.&lt;/p&gt;&lt;p&gt;As an aside, it is interesting to note that Mathematica is one of the languages with a bleak future in the face of multicore computing due to fundamental design issues. Specifically, the Mathematica system is largely built around the Mathematica language which is a term rewrite language evaluated by repeated substitution using symbolic replacement rules. The rules are, by definition, read and written via one giant global rule table and, consequently, direct concurrent use from multiple threads would introduce massive contention for the global table. The only viable solution is to duplicate the entire system separately on each core and communicate via message passing. This foregos the benefits of shared memory offered in a highly-efficient hardware-accelerated form on all multicore computers and, consequently, parallelism in Mathematica is orders of magnitude slower than in other languages. For example, even ignoring the distribution of definitions required to use parallelism in Mathematica, its &lt;span style="font-family:courier new;"&gt;ParallelTable&lt;/span&gt; construct is over 250× slower than the equivalent &lt;span style="font-family:courier new;"&gt;Array.Parallel.init&lt;/span&gt; in F#.&lt;/p&gt;&lt;p&gt;Still, Mathematica's accompanying literature alone justifies the price of just £195!&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-1620233404011990916?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/1620233404011990916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=1620233404011990916' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1620233404011990916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1620233404011990916'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/half-dozen-bugs-in-mathematica-7.html' title='Mathematica 7 review: buggy but fun!'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_NMRkpon4Ps0/TFR79Q7B1pI/AAAAAAAAAIw/3xr1aDtO70I/s72-c/Crash.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-6759074515669909467</id><published>2010-07-27T15:44:00.000-07:00</published><updated>2010-07-27T15:45:16.446-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='london'/><category scheme='http://www.blogger.com/atom/ns#' term='lecture'/><category scheme='http://www.blogger.com/atom/ns#' term='f# meetup'/><title type='text'>F#unctional Londoners meetup lecture (28th July 2010)</title><content type='html'>&lt;p&gt;Zach Bray of &lt;a href="http://www.trayport.com/"&gt;Trayport&lt;/a&gt; and Jon Harrop of &lt;a href="http://www.ffconsultancy.com/?fsb"&gt;Flying Frog Consultancy Ltd.&lt;/a&gt; will be presenting lectures at &lt;a href="http://skillsmatter.com/"&gt;Skills Matter eXchange&lt;/a&gt; London (UK) at 6:30pm on Wednesday 28th July 2010.&lt;/p&gt;&lt;p&gt;Many thanks to Carolyn Miller and Phil Trelford for organizing &lt;a href="http://www.meetup.com/FSharpLondon/"&gt;F#unctional Londoners Meetup Group&lt;/a&gt;, an excellent series of events!&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-6759074515669909467?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/6759074515669909467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=6759074515669909467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6759074515669909467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/6759074515669909467'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/functional-londoners-meetup-lecture.html' title='F#unctional Londoners meetup lecture (28th July 2010)'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-1845923471019094973</id><published>2010-07-22T14:53:00.000-07:00</published><updated>2010-07-22T19:14:42.592-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='hash table'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><title type='text'>Haskell's hash tables revisited: part 2</title><content type='html'>&lt;p&gt;Our &lt;a href="http://flyingfrogblog.blogspot.com/2010/07/haskells-hash-tables-revisited.html"&gt;previous blog post&lt;/a&gt; contained several benchmark results comparing the new GHC 6.12.3 with F#. We have since discovered some other points of interest regarding this benchmark.&lt;/p&gt;&lt;p&gt;Firstly, the results for Haskell rely on the use of a garbage collector that prevents parallelism. If the more modern multicore-friendly GC is used (by compiling with &lt;span style="font-family:courier new;"&gt;-threaded&lt;/span&gt; and running with &lt;span style="font-family:courier new;"&gt;+RTS -N8&lt;/span&gt;) then the time taken increases from 4.5s to 10.6s. This is over 2× slower than before and now over 13× slower than F#. Naturally, the F# was already using the multicore-capable .NET garbage collector so this was an unfair bias in favor of Haskell.&lt;/p&gt;&lt;p&gt;Secondly, the Haskell code exploits an algorithmic optimization on the assumption that the keys are unique. This is often not the case in practice and, again, the F# code did not exploit such an assumption so this was another unfair bias in favor of Haskell. A fairer comparison may be obtained by changing from the &lt;span style="font-family:courier new;"&gt;insert&lt;/span&gt; function to the &lt;span style="font-family:courier new;"&gt;update&lt;/span&gt; function in the Haskell code. Again, this incurs a substantial performance penalty and increases the time taken to 20.6.&lt;/p&gt;&lt;p&gt;With these alterations, Haskell becomes 26× slower than F# on this benchmark even with the latest GHC. Although these latest improvements are a step in the right direction, it seems that Haskell still has a long way to go before attaining competitive performance with mutable data structures.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-1845923471019094973?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/1845923471019094973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=1845923471019094973' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1845923471019094973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/1845923471019094973'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/haskells-hash-tables-revisited-part-2.html' title='Haskell&apos;s hash tables revisited: part 2'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-3064343991024659697</id><published>2010-07-18T16:24:00.000-07:00</published><updated>2010-07-27T16:19:18.079-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='hash table'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Haskell's hash tables revisited</title><content type='html'>&lt;p&gt;Update: We have &lt;a href="http://flyingfrogblog.blogspot.com/2010/07/haskells-hash-tables-revisited-part-2.html"&gt;since discovered&lt;/a&gt; that these results were biased towards Haskell.&lt;/p&gt;&lt;p&gt;Mikhail Glushenkov recently &lt;a href="http://projects.haskell.org/pipermail/haskell-platform/2010-July/001097.html"&gt;announced&lt;/a&gt; the Haskell Platform 2010.2 RC for Windows. In particular, this is the first release to include a version of the Glasgow Haskell Compiler (6.12.3) that has &lt;a href="http://hackage.haskell.org/trac/ghc/ticket/650"&gt;the new garbage collector fix&lt;/a&gt; to address the performance problems Haskell programmers have been experiencing with mutable arrays of boxed values over the past 5 years, such as the spines of hash tables.&lt;/p&gt;&lt;p&gt;Naturally, we couldn't resist benchmarking the new release to see if it lives up to the promise of decent hash table performance. Even though this installer for the Haskell Platform is just a release candidate, we found that it installed smoothly and ran correctly first time.&lt;/p&gt;&lt;p&gt;First up, a repeat of our previous benchmark which inserted 10,000,000 bindings with int keys mapping to int values into an initially-empty hash table:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;GHC 6.12.1: 19.2s&lt;br /&gt;GHC 6.12.3:  4.48s&lt;br /&gt;F# .NET 4:   0.8s&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;The new version of GHC is clearly a substantial improvement over previous versions in this context, completing this benchmark over 4× faster than its predecessor. The fastest Haskell is still 5.6× slower than F# but that is a more reasonable performance difference than before.&lt;/p&gt;&lt;p&gt;Altering the benchmark to build five hash tables containing 5,000,000 bindings each with float keys and values and using the floor or truncate functions as the hash function changes the relative performance considerably:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;GHC 6.12.1: 131s&lt;br /&gt;GHC 6.12.3:  30.2s&lt;br /&gt;F# .NET 4:    2.98s&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;Here, the old GHC is a whopping 44× slower than F# and the latest GHC is still 10× slower.&lt;/p&gt;&lt;p&gt;Surprisingly, this turns out to be a &lt;a href="http://hackage.haskell.org/trac/ghc/ticket/1434"&gt;3 year old performance bug&lt;/a&gt;, this time in the implementation of basic numeric functions. Fortunately, this can be fixed simply by annotating the type of the truncate function. This gives the following performance:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;GHC 6.12.1:  43.8s&lt;br /&gt;GHC 6.12.3:  17.1s&lt;br /&gt;F# .NET 4:    2.98s&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;The latest Haskell is now back to being only 5.7× slower than F#.&lt;/p&gt;&lt;p&gt;Here's the new F# code:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;let cmp =&lt;br /&gt;  { new System.Object()&lt;br /&gt;      interface System.Collections.Generic.IEqualityComparer&lt;float&gt; with&lt;br /&gt;        member this.Equals(x, y) = x=y&lt;br /&gt;        member this.GetHashCode x = int x }&lt;br /&gt;for _ in 1..5 do&lt;br /&gt;  let m = System.Collections.Generic.Dictionary(cmp)&lt;br /&gt;  for i=5000000 downto 1 do&lt;br /&gt;    m.[float i] &lt;- float i&lt;br /&gt;  printfn "m[42] = %A" m.[42.0]&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;And here's the new Haskell code:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;import qualified Data.HashTable as H&lt;br /&gt;import GHC.Float&lt;br /&gt;&lt;br /&gt;act 0 = return ()&lt;br /&gt;act n = do&lt;br /&gt;  ht &lt;- H.new (==) (fromIntegral . (truncate :: Double -&gt; Int)) :: IO (H.HashTable Double Double)&lt;br /&gt;  let loop 0 = return ()&lt;br /&gt;      loop i = do&lt;br /&gt;          H.insert ht (fromIntegral i) (fromIntegral $ i+n)&lt;br /&gt;          loop (i-1)&lt;br /&gt;  loop (5*(10^6))&lt;br /&gt;  ans &lt;- H.lookup ht 42.0&lt;br /&gt;  print ans&lt;br /&gt;  act (n-1)&lt;br /&gt;&lt;br /&gt;main :: IO ()&lt;br /&gt;main = act 5&lt;/p&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-3064343991024659697?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/3064343991024659697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=3064343991024659697' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3064343991024659697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3064343991024659697'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/haskells-hash-tables-revisited.html' title='Haskell&apos;s hash tables revisited'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-4453328360598135483</id><published>2010-07-12T17:04:00.000-07:00</published><updated>2010-07-12T17:23:32.098-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conservative gc'/><category scheme='http://www.blogger.com/atom/ns#' term='mono'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><title type='text'>Mono 2.4 still leaking like a sieve</title><content type='html'>&lt;p&gt;How fast are hash tables in Mono 2.4 compared to .NET 4? An excellent question but one which led us to another trivial program that leaks memory on Mono but not on .NET (we previously gave &lt;a href="http://flyingfrogblog.blogspot.com/2009/01/mono-22-still-leaks-memory.html"&gt;a simple stack implementation written in F# that leaked memory on Mono 2.2&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;We tried to use the following benchmark program to measure Mono's performance when filling a hash table from empty with &lt;span style="font-family:courier new;"&gt;float&lt;/span&gt; keys and values:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#102;&amp;#111;&amp;#114;&amp;#032;&amp;#105;&amp;#032;&amp;#105;&amp;#110;&amp;#032;&amp;#049;&amp;#046;&amp;#046;&amp;#049;&amp;#048;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#116;&amp;#032;&amp;#061;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#068;&amp;#105;&amp;#097;&amp;#103;&amp;#110;&amp;#111;&amp;#115;&amp;#116;&amp;#105;&amp;#099;&amp;#115;&amp;#046;&amp;#083;&amp;#116;&amp;#111;&amp;#112;&amp;#119;&amp;#097;&amp;#116;&amp;#099;&amp;#104;&amp;#046;&amp;#083;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#078;&amp;#101;&amp;#119;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#109;&amp;#032;&amp;#061;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#067;&amp;#111;&amp;#108;&amp;#108;&amp;#101;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#046;&amp;#071;&amp;#101;&amp;#110;&amp;#101;&amp;#114;&amp;#105;&amp;#099;&amp;#046;&amp;#068;&amp;#105;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#097;&amp;#114;&amp;#121;&amp;#040;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#108;&amp;#101;&amp;#116;&amp;#032;&amp;#109;&amp;#117;&amp;#116;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#032;&amp;#120;&amp;#032;&amp;#061;&amp;#032;&amp;#048;&amp;#046;&amp;#048;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#102;&amp;#111;&amp;#114;&amp;#032;&amp;#105;&amp;#061;&amp;#049;&amp;#032;&amp;#116;&amp;#111;&amp;#032;&amp;#049;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#032;&amp;#100;&amp;#111;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#109;&amp;#046;&amp;#091;&amp;#120;&amp;#093;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#120;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#032;&amp;#032;&amp;#120;&amp;#032;&amp;#060;&amp;#045;&amp;#032;&amp;#120;&amp;#032;&amp;#043;&amp;#032;&amp;#049;&amp;#046;&amp;#048;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&amp;#102;&amp;#110;&amp;#032;&amp;#034;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#037;&amp;#103;&amp;#034;&amp;#032;&amp;#109;&amp;#046;&amp;#091;&amp;#052;&amp;#050;&amp;#046;&amp;#048;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#112;&amp;#114;&amp;#105;&amp;#110;&amp;#116;&amp;#102;&amp;#110;&amp;#032;&amp;#034;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#037;&amp;#103;&amp;#115;&amp;#092;&amp;#110;&amp;#034;&amp;#032;&amp;#116;&amp;#046;&amp;#069;&amp;#108;&amp;#097;&amp;#112;&amp;#115;&amp;#101;&amp;#100;&amp;#046;&amp;#084;&amp;#111;&amp;#116;&amp;#097;&amp;#108;&amp;#083;&amp;#101;&amp;#099;&amp;#111;&amp;#110;&amp;#100;&amp;#115;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;Here's the output of that program on Mono 2.4:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&amp;#036;&amp;#032;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#032;&amp;#072;&amp;#097;&amp;#115;&amp;#104;&amp;#084;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#066;&amp;#101;&amp;#110;&amp;#099;&amp;#104;&amp;#109;&amp;#097;&amp;#114;&amp;#107;&amp;#046;&amp;#101;&amp;#120;&amp;#101;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#052;&amp;#053;&amp;#048;&amp;#057;&amp;#057;&amp;#115;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#050;&amp;#052;&amp;#051;&amp;#049;&amp;#115;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#051;&amp;#046;&amp;#051;&amp;#057;&amp;#050;&amp;#056;&amp;#056;&amp;#115;&amp;#013;&amp;#010;&amp;#109;&amp;#091;&amp;#052;&amp;#050;&amp;#093;&amp;#032;&amp;#061;&amp;#032;&amp;#052;&amp;#050;&amp;#013;&amp;#010;&amp;#084;&amp;#111;&amp;#111;&amp;#107;&amp;#032;&amp;#050;&amp;#055;&amp;#046;&amp;#050;&amp;#051;&amp;#053;&amp;#050;&amp;#115;&amp;#013;&amp;#010;&amp;#013;&amp;#010;&amp;#085;&amp;#110;&amp;#104;&amp;#097;&amp;#110;&amp;#100;&amp;#108;&amp;#101;&amp;#100;&amp;#032;&amp;#069;&amp;#120;&amp;#099;&amp;#101;&amp;#112;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#058;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#079;&amp;#117;&amp;#116;&amp;#079;&amp;#102;&amp;#077;&amp;#101;&amp;#109;&amp;#111;&amp;#114;&amp;#121;&amp;#069;&amp;#120;&amp;#099;&amp;#101;&amp;#112;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#058;&amp;#032;&amp;#079;&amp;#117;&amp;#116;&amp;#032;&amp;#111;&amp;#102;&amp;#032;&amp;#109;&amp;#101;&amp;#109;&amp;#111;&amp;#114;&amp;#121;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#040;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#032;&amp;#109;&amp;#097;&amp;#110;&amp;#097;&amp;#103;&amp;#101;&amp;#100;&amp;#045;&amp;#116;&amp;#111;&amp;#045;&amp;#110;&amp;#097;&amp;#116;&amp;#105;&amp;#118;&amp;#101;&amp;#041;&amp;#032;&amp;#111;&amp;#098;&amp;#106;&amp;#101;&amp;#099;&amp;#116;&amp;#058;&amp;#095;&amp;#095;&amp;#105;&amp;#099;&amp;#097;&amp;#108;&amp;#108;&amp;#095;&amp;#119;&amp;#114;&amp;#097;&amp;#112;&amp;#112;&amp;#101;&amp;#114;&amp;#095;&amp;#109;&amp;#111;&amp;#110;&amp;#111;&amp;#095;&amp;#097;&amp;#114;&amp;#114;&amp;#097;&amp;#121;&amp;#095;&amp;#110;&amp;#101;&amp;#119;&amp;#095;&amp;#115;&amp;#112;&amp;#101;&amp;#099;&amp;#105;&amp;#102;&amp;#105;&amp;#099;&amp;#032;&amp;#040;&amp;#105;&amp;#110;&amp;#116;&amp;#112;&amp;#116;&amp;#114;&amp;#044;&amp;#105;&amp;#110;&amp;#116;&amp;#041;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#067;&amp;#111;&amp;#108;&amp;#108;&amp;#101;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#046;&amp;#071;&amp;#101;&amp;#110;&amp;#101;&amp;#114;&amp;#105;&amp;#099;&amp;#046;&amp;#068;&amp;#105;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#097;&amp;#114;&amp;#121;&amp;#096;&amp;#050;&amp;#091;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#068;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#044;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#068;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#093;&amp;#046;&amp;#082;&amp;#101;&amp;#115;&amp;#105;&amp;#122;&amp;#101;&amp;#032;&amp;#040;&amp;#041;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#067;&amp;#111;&amp;#108;&amp;#108;&amp;#101;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#115;&amp;#046;&amp;#071;&amp;#101;&amp;#110;&amp;#101;&amp;#114;&amp;#105;&amp;#099;&amp;#046;&amp;#068;&amp;#105;&amp;#099;&amp;#116;&amp;#105;&amp;#111;&amp;#110;&amp;#097;&amp;#114;&amp;#121;&amp;#096;&amp;#050;&amp;#091;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#068;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#044;&amp;#083;&amp;#121;&amp;#115;&amp;#116;&amp;#101;&amp;#109;&amp;#046;&amp;#068;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#093;&amp;#046;&amp;#115;&amp;#101;&amp;#116;&amp;#095;&amp;#073;&amp;#116;&amp;#101;&amp;#109;&amp;#032;&amp;#040;&amp;#068;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#032;&amp;#107;&amp;#101;&amp;#121;&amp;#044;&amp;#032;&amp;#068;&amp;#111;&amp;#117;&amp;#098;&amp;#108;&amp;#101;&amp;#032;&amp;#118;&amp;#097;&amp;#108;&amp;#117;&amp;#101;&amp;#041;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#093;&amp;#013;&amp;#010;&amp;#032;&amp;#032;&amp;#097;&amp;#116;&amp;#032;&amp;#060;&amp;#083;&amp;#116;&amp;#097;&amp;#114;&amp;#116;&amp;#117;&amp;#112;&amp;#067;&amp;#111;&amp;#100;&amp;#101;&amp;#036;&amp;#072;&amp;#097;&amp;#115;&amp;#104;&amp;#084;&amp;#097;&amp;#098;&amp;#108;&amp;#101;&amp;#066;&amp;#101;&amp;#110;&amp;#099;&amp;#104;&amp;#109;&amp;#097;&amp;#114;&amp;#107;&amp;#062;&amp;#046;&amp;#036;&amp;#080;&amp;#114;&amp;#111;&amp;#103;&amp;#114;&amp;#097;&amp;#109;&amp;#046;&amp;#109;&amp;#097;&amp;#105;&amp;#110;&amp;#064;&amp;#032;&amp;#040;&amp;#041;&amp;#032;&amp;#091;&amp;#048;&amp;#120;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#048;&amp;#093;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;Even more surprisingly, this program still dies with out of memory even if we explicitly &lt;span style="font-family:courier new;"&gt;Clear&lt;/span&gt; the hash table after every iteration!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-4453328360598135483?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/4453328360598135483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=4453328360598135483' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4453328360598135483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/4453328360598135483'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/mono-24-still-leaking-like-sieve.html' title='Mono 2.4 still leaking like a sieve'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-8206294041587248357</id><published>2010-07-12T15:33:00.001-07:00</published><updated>2010-07-12T15:34:07.342-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='animation'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematica'/><title type='text'>Animated Mathematica functions</title><content type='html'>&lt;p&gt;Here's &lt;a href="http://documents.wolfram.com/flash/"&gt;a fun web page&lt;/a&gt; from Wolfram Research that has animations for a bunch of Mathematica's built-in functions.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-8206294041587248357?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/8206294041587248357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=8206294041587248357' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8206294041587248357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/8206294041587248357'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/animated-mathematica-functions.html' title='Animated Mathematica functions'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-5611319262973631023</id><published>2010-07-12T05:49:00.000-07:00</published><updated>2010-07-12T16:34:52.271-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='o&apos;reilly'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><category scheme='http://www.blogger.com/atom/ns#' term='sal mangano'/><category scheme='http://www.blogger.com/atom/ns#' term='mathematica'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>Book review: Mathematica Cookbook by Sal Mangano</title><content type='html'>&lt;p&gt;O'Reilly just published a new book, the &lt;a href="http://oreilly.com/catalog/9780596521004"&gt;Mathematica Cookbook&lt;/a&gt;, about Wolfram Research's flagship product. This book contains many interesting examples from various different disciplines. Most of these are derived from freely available examples written by other people (primarily from Wolfram Research's original Mathematica Book and also the excellent &lt;a href="http://demonstrations.wolfram.com/"&gt;Wolfram Demonstrations Project&lt;/a&gt;) but the author has simplified some of the programs to make them more accessible.&lt;/p&gt;&lt;p&gt;However, the density of the information in this book is incredibly low. Most pages are filled with superfluous Mathematica output that is often not even described in the text:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Dozens of triples on page 15.&lt;/li&gt;&lt;li&gt;Page 58 lists hundreds of numbers but the text does not even describe their significance.&lt;/li&gt;&lt;li&gt;Page 205 lists all of the words with a subset of the letters "thanksgiv".&lt;/li&gt;&lt;li&gt;Page 226 is raw XML data.&lt;/li&gt;&lt;li&gt;Pages 264-265 are solid code that renders a snowman with circles and some dots for snow (all in black and white).&lt;/li&gt;&lt;li&gt;Pages 303-304 are two more pages of code to plot a snowman in 3D.&lt;/li&gt;&lt;li&gt;Page 321 lists all of the properties in Mathematica's polyhedron database and page 322 draws 20 polyhedra before page 324 enumerates exactly the same polyhedron properties again.&lt;/li&gt;&lt;li&gt;Pages 334-335 enumerate image data numerically (three times).&lt;/li&gt;&lt;li&gt;Page 359 displays quadrant swapping with 25x more matrix elements than necessary.&lt;/li&gt;&lt;li&gt;Page 360 is the Fourier transform of an image and page 361 is an apparently identical one.&lt;/li&gt;&lt;li&gt;Page 507 lists every chemical element and page 571 lists every property of them.&lt;/li&gt;&lt;li&gt;Page 553 lists every property available for financial data and page 554 lists them all over again.&lt;/li&gt;&lt;li&gt;Page 572 contains an empty graph.&lt;/li&gt;&lt;li&gt;and so on...&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Many pages are devoted to &lt;span style="font-family:courier new;"&gt;TreeForm&lt;/span&gt; plots of trees that convey no useful information, e.g. the trees drawn on page 129 in the section about red-black trees:&lt;/p&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/_NMRkpon4Ps0/TDt8TqBEVOI/AAAAAAAAAIM/UDLa8XYMp24/s1600/TreeForm.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 361px; DISPLAY: block; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5493120847646577890" border="0" alt="" src="http://4.bp.blogspot.com/_NMRkpon4Ps0/TDt8TqBEVOI/AAAAAAAAAIM/UDLa8XYMp24/s400/TreeForm.png" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Would have been nice to see red and black colored nodes or even learn how to do that using Mathematica (assuming it is possible). In particular, half of page 115 is a &lt;span style="font-family:courier new;"&gt;TreeForm&lt;/span&gt; view so badly laid out by Mathematica that it is unreadable.&lt;/p&gt;&lt;p&gt;There are also some problems with the technical content itself. For example, the section on red-black trees is a simple translation from Okasaki's excellent book "Purely functional data structures". The only new functionality Sal Mangano added is a &lt;span style="font-family:courier new;"&gt;remove&lt;/span&gt; function but his implementation is completely wrong.&lt;/p&gt;&lt;p&gt;The book is chocked full of advice about optimization. This is both good and bad. Good because Mathematica users need all the help they can get with performance because Mathematica is so slow. Bad because the best advice for a Mathematica user when performance is even vaguely relevant is to ditch Mathematica in favor of a more modern tool with better performance. For example, section 14.10 "Compiling an Implementation of Explicit Trinomial for Fast Pricing of American Options" states that "You need a very fast pricer for American options" but the fastest Mathematica code given can be &lt;a href="http://fsharpnews.blogspot.com/2010/07/f-vs-mathematica-even-faster-pricer-for.html"&gt;a whopping 960× slower than a comparably-simple F# solution&lt;/a&gt;. Furthermore, it turns out that this was not written by Sal Mangano (the author of the book) but by &lt;a href="http://216.80.120.13:8080/webMathematica/LC/explicit.jsp"&gt;Andreas Lauschke&lt;/a&gt; (a Mathematica and Java consultant) and it is a translation of MATLAB code written by Ansgar Jüngel (an academic).&lt;/p&gt;&lt;p&gt;There are several multi-page program listings written as plain Mathematica code with embedded comments that are difficult to read (they are not even spaced out, let alone typeset properly!) instead of prose. Page 265 is a block of code, for example:&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/_NMRkpon4Ps0/TDuHaOGkcHI/AAAAAAAAAIU/orl8FiMl8eM/s1600/MathematicaCookbookPage265.jpg"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 306px; DISPLAY: block; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5493133055040450674" border="0" alt="" src="http://2.bp.blogspot.com/_NMRkpon4Ps0/TDuHaOGkcHI/AAAAAAAAAIU/orl8FiMl8eM/s400/MathematicaCookbookPage265.jpg" /&gt;&lt;/a&gt; &lt;p&gt;Although the book does contain a frustrating amount of blatant filler, it is very cheap (O'Reilly) and does contain several thought-provoking examples. Whether you use Mathematica or not, you'll probably learn something useful about the state-of-the-art in the Mathematica world by skimming this book. On a higher level, you will probably learn a lot more about business if you consider what this book and the army of Mathematica devotees behind it represent. After all, there is a lot of money in starting a religion!&lt;/p&gt;&lt;p&gt;FWIW, here are the interesting references from the book to original sources:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cs.utep.edu/interval-comp/"&gt;Interval Computations&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/algoen.htm"&gt;Sequential and parallel sorting algorithms&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://nova.umuc.edu/~jarc/idsv/lesson1.html"&gt;Interactive data structure visualizations&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://norvig.com/spell-correct.html"&gt;How to write a spelling corrector&lt;/a&gt; by Peter Norvig (of Google).&lt;/li&gt;&lt;li&gt;&lt;a href="http://library.wolfram.com/conferences/devconf99/lichtblau/"&gt;Data structures and efficient algorithms in Mathematica&lt;/a&gt; by Daniel Lichtblau.&lt;/li&gt;&lt;li&gt;&lt;a href="http://pdos.csail.mit.edu/~baford/packrat/"&gt;Packrat parsing&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.wolfram.com/2009/09/11/twisted-architecture/"&gt;Twisted architecture&lt;/a&gt; by Chris Carlson.&lt;/li&gt;&lt;li&gt;&lt;a href="http://fourier.eng.hmc.edu/e161/lectures/contrast_transform/node3.html"&gt;Histogram equalization&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://cvc.yale.edu/projects/yalefaces/yalefaces.html"&gt;The Yale face database&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cs.otago.ac.nz/cosc453/student_tutorials/principal_components.pdf"&gt;A tutorial on Principal Components Analysis&lt;/a&gt; by Lindsay I Smith.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.math.upenn.edu/~wilf/gfology2.pdf"&gt;Generatingfunctionology&lt;/a&gt; by Hilbert S Wilf.&lt;/li&gt;&lt;li&gt;&lt;a href="http://demonstrations.wolfram.com/PredatorPreyDynamicsWithTypeTwoFunctionalResponse/"&gt;Predator-Prey dynamics with type-2 functional response&lt;/a&gt; by Wilfried Gabriel.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.sv.vt.edu/classes/MSE2094_NoteBook/97ClassProj/num/midkiff/theory.html"&gt;Theory of Finite Element Analysis&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.weber-und-partner.com/resources/index.htm"&gt;Finance-related Mathematica resources&lt;/a&gt; from Weber &amp;amp; Partner.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-5611319262973631023?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/5611319262973631023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=5611319262973631023' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5611319262973631023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/5611319262973631023'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/book-review-mathematica-cookbook-by-sal.html' title='Book review: Mathematica Cookbook by Sal Mangano'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_NMRkpon4Ps0/TDt8TqBEVOI/AAAAAAAAAIM/UDLa8XYMp24/s72-c/TreeForm.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-3411979208699458013</id><published>2010-07-05T01:48:00.001-07:00</published><updated>2010-07-05T01:56:46.208-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='bloxors'/><category scheme='http://www.blogger.com/atom/ns#' term='game'/><title type='text'>Purely functional games</title><content type='html'>&lt;p&gt;A recent blog post entitled "&lt;a href="http://prog21.dadgum.com/55.html"&gt;Follow up to functional programming doesn't work&lt;/a&gt;" recently caused a bit of a stir, encouraging Haskell programmers to dredge up the nearest things Haskell has to real computer games. A &lt;a href="http://www.youtube.com/watch?v=gVLFGQGRsDw"&gt;Super Mario clone&lt;/a&gt;, &lt;a href="http://www.youtube.com/watch?v=0jYdu2u8gAU"&gt;Frag&lt;/a&gt; (a reimplementation of part of Quake), a &lt;a href="http://www.youtube.com/watch?v=zqFgQiPKtOI"&gt;Gradius clone&lt;/a&gt;, &lt;a href="http://www.youtube.com/watch?v=PUJs9RTnZjc"&gt;4Blocks&lt;/a&gt; and a game that blows all of the others away called Bloxors:&lt;/p&gt;&lt;p&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/AJQZg3Po-Ag&amp;amp;hl=en_GB&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/AJQZg3Po-Ag&amp;amp;hl=en_GB&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;&lt;p&gt;This beautiful little OpenGL-based puzzle game weighs in at just 613 lines of purely functional code (many of the other games use &lt;span style="font-family:courier new;"&gt;unsafe*&lt;/span&gt; functions to introduce uncontrolled side effects). This is also one of the few programs that &lt;span style="font-family:courier new;"&gt;cabal install&lt;/span&gt; actually works on.&lt;/p&gt;&lt;p&gt;Check it out &lt;a href="http://hackage.haskell.org/package/bloxorz"&gt;here&lt;/a&gt;!&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-3411979208699458013?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/3411979208699458013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=3411979208699458013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3411979208699458013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/3411979208699458013'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/purely-functional-games.html' title='Purely functional games'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-7077422685965021731</id><published>2010-07-02T13:47:00.000-07:00</published><updated>2010-07-02T14:59:07.096-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cpu'/><category scheme='http://www.blogger.com/atom/ns#' term='intel'/><category scheme='http://www.blogger.com/atom/ns#' term='gpu'/><title type='text'>Debunking the 100× GPU vs. CPU myth</title><content type='html'>&lt;p&gt;Intel recently published a paper with no less than 12 authors called &lt;a href="http://portal.acm.org/citation.cfm?id=1816021&amp;amp;coll=GUIDE&amp;amp;dl=GUIDE&amp;amp;CFID=11111111&amp;amp;CFTOKEN=2222222&amp;amp;ret=1#"&gt;&lt;em&gt;Debunking the 100X GPU vs. CPU myth: an evaluation of throughput computing on CPU and GPU&lt;/em&gt;&lt;/a&gt; where they criticize the huge performance discrepancies cited by researchers publishing about General-Purpose GPU (GPGPU) programming in the context of what they call "throughput computing".&lt;/p&gt;&lt;p&gt;We have also noticed bad science in this domain before. We tried to reproduce the incredible results of one paper, with a view to entering this market ourselves, only to discover they had used the reference implementation of LAPACK instead of the vendor tuned implementation for their CPU that was 10× faster. Like Intel, we found that the performance advantage of a GPU was relatively modest (2.5×) given the enormous costs and liabilities of using a GPU for number crunching. However, we are fortunate to be able to simply dismiss fantastical results as irrelevant propaganda but Intel are presumably feeling the pinch as misinformed customers flock to buy nVidia's GPUs to attack problems for which a better Intel CPU would have been more appropriate.&lt;/p&gt;&lt;p&gt;On the other hand, the failure of manycore GPUs to attain competitive performance for all but a handful of tasks raises the question of how much general software stands to gain from the multicore revolution? Is this the end of the line for performance as we know it?&lt;/p&gt;&lt;p&gt;Intel's careful use of the phrase "throughput computing" is significant. Their point is that memory hierarchies are the shared headache. Applications that perform local computations in registers without need of external data can easily be made to scale extremely well. Computing Mandelbrot fractals is one example of this. For example, GPUs should excel at rendering the complex Mandelbulb fractal that was discovered in recent years:&lt;/p&gt;&lt;p&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/eKUh4nkmQbc&amp;amp;hl=en_GB&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/eKUh4nkmQbc&amp;amp;hl=en_GB&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;&lt;p&gt;Awesome stuff, but what is it useful for?&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1779668156488517434-7077422685965021731?l=flyingfrogblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flyingfrogblog.blogspot.com/feeds/7077422685965021731/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1779668156488517434&amp;postID=7077422685965021731' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/7077422685965021731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1779668156488517434/posts/default/7077422685965021731'/><link rel='alternate' type='text/html' href='http://flyingfrogblog.blogspot.com/2010/07/debunking-100-gpu-vs-cpu-myth.html' title='Debunking the 100&amp;#215; GPU vs. CPU myth'/><author><name>Flying Frog Consultancy Ltd.</name><uri>http://www.blogger.com/profile/11059316496121100950</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1779668156488517434.post-2243973040888398821</id><published>2010-06-18T16:05:00.001-07:00</published><updated>2010-07-12T11:43:13.308-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='don stewart'/><category scheme='http://www.blogger.com/atom/ns#' term='hash table'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='norman ramsey'/><category scheme='http://www.blogger.com/atom/ns#' term='ganesh sittampalam'/><title type='text'>Haskell's hash table woes (again)</title><content type='html'>&lt;p&gt;Alessandro Stamatto recently asked &lt;a href="http://stackoverflow.com/questions/3058529/curious-about-the-hashtable-problem/"&gt;a question&lt;/a&gt; on Stack Overflow about the current state of Haskell's hash tables following &lt;a href="http://flyingfrogblog.blogspot.com/2009/04/f-vs-ocaml-vs-haskell-hash-table.html"&gt;our rediscovery last year that Haskell's hash tables were up to 32× slower than common alternatives like C++ and .NET&lt;/a&gt; and even slower than Python.&lt;/p&gt;&lt;p&gt;Don Stewart &lt;a href="http://stackoverflow.com/posts/3058529/revisions"&gt;edited Alessandro's original question&lt;/a&gt;, deleting the citation to the original study that provided a verifiable experiment with complete code, before writing an answer claiming that 
