<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>anil.recoil.org</title>
 <link href="http://anil.recoil.org/feeds/atom.xml" rel="self"/>
 <link href="http://anil.recoil.org"/>
 <updated>2013-01-20T12:41:19+00:00</updated>
 <id>http://anil.recoil.org</id>
 <author>
   <name>Anil Madhavapeddy</name>
   <email>anil@recoil.org</email>
 </author>
 
 
 <entry>
   <title>Announcing the OCaml Labs project</title>
   <link href="http://anil.recoil.org/2012/10/19/announcing-ocaml-labs.html"/>
   <updated>2012-10-19T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2012/10/19/announcing-ocaml-labs</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m very excited to announce &lt;em&gt;&lt;a href='http://www.cl.cam.ac.uk/projects/ocamllabs'&gt;OCaml Labs&lt;/a&gt;&lt;/em&gt;, the latest project to hit the Cambridge Computer Lab. As anyone that hangs out near me probably realises, I very much enjoy functional programming. My weapon of choice tends to be &lt;a href='http://www.ocaml-lang.org'&gt;OCaml&lt;/a&gt;, as it condenses &lt;a href='http://events.inf.ed.ac.uk/Milner2012/X_Leroy-html5-mp4.html'&gt;decades of research&lt;/a&gt; into a pragmatic blend of functional, imperative and object-oriented programming styles. What&amp;#8217;s perhaps less well known are the steady &lt;a href='http://www.ocaml-lang.org/companies.html'&gt;inroads&lt;/a&gt; that OCaml has been making into mission-critical areas of industry. At &lt;a href='http://ocaml.janestreet.com'&gt;Jane Street&lt;/a&gt;, billions of dollars of transactions are routed through a huge ML code-base that is designed to catch bugs &lt;a href='http://vimeo.com/14313378'&gt;at compile-time&lt;/a&gt;. At &lt;a href='http://github.com/xen-org/xen-api'&gt;Citrix&lt;/a&gt;, the Xen management toolstack that powers &lt;a href='http://blogs.citrix.com/2012/10/09/one-in-a-million/'&gt;millions&lt;/a&gt; of hosts in the cloud is &lt;a href='http://anil.recoil.org/papers/2010-icfp-xen.pdf'&gt;largely written in OCaml&lt;/a&gt;. Facebook does sophisticated &lt;a href='https://github.com/facebook/pfff/wiki/Main'&gt;static analysis&lt;/a&gt; using OCaml over their vast PHP codebase to close security holes.&lt;/p&gt;

&lt;p&gt;The OCaml community is small but dedicated, but there is always more to do to improve the language and ecosystem. So, thanks to a generous platform grant from &lt;a href='http://ocaml.janestreet.com'&gt;Jane Street&lt;/a&gt;, we are launching a program to help with the open-source development of OCaml from Cambridge.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;&lt;a href='http://www.cl.cam.ac.uk/projects/ocamllabs/'&gt;OCaml Labs&lt;/a&gt;&lt;/em&gt; are based in the &lt;a href='http://www.cl.cam.ac.uk'&gt;Cambridge Computer Lab&lt;/a&gt; and led my myself, &lt;a href='http://www.cl.cam.ac.uk/~am21/'&gt;Alan Mycroft&lt;/a&gt; and &lt;a href='http://www.cl.cam.ac.uk/~iml1/'&gt;Ian Leslie&lt;/a&gt;. We&amp;#8217;re closely affiliated with other &lt;a href='http://www.cl.cam.ac.uk/projects/ocamllabs/collaboration.html'&gt;groups&lt;/a&gt;, and will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;developing the OCaml Platform, which will bundle the official OCaml compiler from INRIA with a tested set of community libraries that refreshed every six months.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;working with the core OCaml team at INRIA&amp;#8217;s &lt;a href='http://gallium.inria.fr/'&gt;Gallium&lt;/a&gt; group on the compiler, and with commercial partners like &lt;a href='http://ocamlpro.com'&gt;OCamlPro&lt;/a&gt; on tool development. OCamlPro are making some very impressive progress already with the &lt;a href='http://opam.ocamlpro.com'&gt;OPAM&lt;/a&gt; packge manager and &lt;a href='http://www.typerex.org'&gt;TypeRex&lt;/a&gt; IDE helper.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;supporting the online presence with more teaching material and content. Yaron, Jason and I are working hard on a &lt;a href='http://realworldocaml.org'&gt;new book&lt;/a&gt; that will be published next year, and the OCaml Web team (led by &lt;a href='http://ashishagarwal.org'&gt;Ashish&lt;/a&gt; and &lt;a href='https://plus.google.com/109604597514379193052/posts'&gt;Christophe&lt;/a&gt;) have made great progress on a &lt;a href='http://www.ocaml-lang.org'&gt;brand new website&lt;/a&gt; that we will move to the &lt;code&gt;ocaml.org&lt;/code&gt; domain soon.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='research_efforts'&gt;Research efforts&lt;/h3&gt;

&lt;p&gt;Of course, it is difficult to hack on a language in a void, and we also &lt;em&gt;use&lt;/em&gt; OCaml heavily in our own research. The other half of OCaml Lab&amp;#8217;s goals are more disruptive (and riskier!):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The upcoming first beta release of &lt;a href='http://openmirage.org'&gt;Mirage&lt;/a&gt;, which is an operating system designed for cloud and embedded environments, and is written almost entirely from the ground up in OCaml. The outputs of Mirage include a &lt;a href='http://www.openmirage.org/blog/breaking-up-is-easy-with-opam'&gt;large number of libraries&lt;/a&gt; which are usable separately, such as pure implementations of TCP/IP, DNS, SSH, DHCP and HTTP. The Xen hackers, led by &lt;a href='http://dave.recoil.org'&gt;David Scott&lt;/a&gt;, are out in force to integrate Mirage into their &lt;a href='http://www.xen.org/xensummit/xs12na_talks/T2.html'&gt;next-generation&lt;/a&gt; platform. Meanwhile, Raphael Proust is busy eliminating the &lt;a href='http://anil.recoil.org/papers/drafts/2012-places-limel-draft1.pdf'&gt;garbage collector&lt;/a&gt; with his cut-down &amp;#8220;LinearML&amp;#8221; variant.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Working with our collaborators at the &lt;a href='http://horizon.ac.uk'&gt;Horizon Institute&lt;/a&gt; on privacy-preserving technologies such as &lt;a href='http://anil.recoil.org/papers/2012-sigcomm-signposts-demo.pdf'&gt;Signposts&lt;/a&gt; which let you build and maintain your own personal clouds that operate &lt;a href='http://anil.recoil.org/papers/2011-icdcn-droplets.pdf'&gt;autonomously&lt;/a&gt; from the central cloud. You can read more about our &lt;a href='http://www.cam.ac.uk/research/features/privacy-by-design/'&gt;privacy-by-design&lt;/a&gt; philosophy too.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Extending OCaml to run on secure hardware platforms that doesn&amp;#8217;t compromise on performance, using the MIPS64-based &lt;a href='http://www.cl.cam.ac.uk/research/security/ctsrd/cheri.html'&gt;capability processor&lt;/a&gt; that is being developed at at the Lab.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The &lt;a href='http://www.trilogy-project.org'&gt;Trilogy&lt;/a&gt; was a hugely successful EU-funded effort on future evolution of the Internet, and resulted in &lt;a href='http://trilogy-project.org/publications/standards-contributions.html'&gt;numerous RFCs&lt;/a&gt; on subjects such as multipath-TCP. We&amp;#8217;re partipating in the follow-up (imaginatively dubbed &amp;#8220;Trilogy2&amp;#8221;), and look forward to working on more structured abstractions for programming large-scale networks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='getting_involved'&gt;Getting involved&lt;/h3&gt;

&lt;p&gt;So, how can you get involved? We are initially advertising three positions for full-time developers and researchers (&lt;a href='http://www.jobs.cam.ac.uk/job/-21662/'&gt;junior&lt;/a&gt; and &lt;a href='http://www.jobs.cam.ac.uk/job/-21942/'&gt;senior&lt;/a&gt;) to help us get started with the OCaml Platform and compiler development. These aren&amp;#8217;t conventional pure research jobs, and a successful candidate should enjoy the open-source development cycle (you retain your own copyright for your own projects). The Computer Lab offers a pretty unique environment: a friendly, non-hierarchical group in a beautiful city, and some of the best faculty and students you could hope to hang out with.&lt;/p&gt;

&lt;p&gt;And finally, there is a longer lead time on &lt;a href='http://www.cl.cam.ac.uk/admissions/phd/'&gt;applying for PhDs&lt;/a&gt;, but this is a great time to get involved. When I started at the Lab in 2002, a little project called &lt;a href='http://xen.org'&gt;Xen&lt;/a&gt; was just kicking off, and many of us had a wild (and oft great) time riding that wave. Get in touch with myself, &lt;a href='http://www.cl.cam.ac.uk/~am21/'&gt;Alan&lt;/a&gt;, &lt;a href='http://www.cl.cam.ac.uk/~iml1/'&gt;Ian&lt;/a&gt; or &lt;a href='http://www.cl.cam.ac.uk/~jac22/'&gt;Jon&lt;/a&gt; soon if you are interested in applying! There&amp;#8217;s some more information available on the &lt;a href='http://www.cl.cam.ac.uk/projects/ocamllabs/collaboration.html'&gt;OCaml Labs pages&lt;/a&gt; about options.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Why you should go to ICFP 2012</title>
   <link href="http://anil.recoil.org/2012/07/31/the-functional-week.html"/>
   <updated>2012-07-31T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2012/07/31/the-functional-week</id>
   <content type="html">&lt;p&gt;Functional programming has been gaining popularity pretty rapidly recently. We&amp;#8217;ve got serious projects from big Internet shops (&lt;a href='http://cufp.org/videos/f-embracing-functional-programming-visual-studio-2010-luke-hoban-mic'&gt;Microsoft&lt;/a&gt;, &lt;a href='http://cufp.org/videos/large-scale-internet-services-using-scala'&gt;Twitter&lt;/a&gt; and &lt;a href='http://cufp.org/videos/functional-programming-facebook'&gt;Facebook&lt;/a&gt;), to varied domains such as &lt;a href='http://cufp.org/videos/fourteen-days-haskell'&gt;radio&lt;/a&gt;, &lt;a href='http://cufp.org/videos/functional-programming-freebase-warren-harris-metaweb'&gt;knowledge
bases&lt;/a&gt;, &lt;a href='http://cufp.org/videos/discrete-event-simulation-using-erlang'&gt;the energy
grid&lt;/a&gt;, &lt;a href='http://cufp.org/videos/theorem-based-derivation-aes-implementation'&gt;cryptography&lt;/a&gt;, NoSQL &lt;a href='http://cufp.org/conference/sessions/2010/riak-core-building-distributed-applications-withou'&gt;databases&lt;/a&gt; and &lt;a href='http://cufp.org/videos/ocaml-and-acunu-experience-report'&gt;storage&lt;/a&gt;, intricate &lt;a href='http://cufp.org/videos/functional-mzscheme-dsls-game-development'&gt;PS3 games&lt;/a&gt;, and even &lt;a href='http://cufp.org/videos/model-based-testing-autosar-automotive-components'&gt;making
safer cars&lt;/a&gt;. Throughout all of this, one conference has been around since the very beginning: the &lt;a href='http://icfpconference.org/'&gt;ACM SIGPLAN
International Conference on Functional Programming&lt;/a&gt;. The early days consisted of academics (some with fine &lt;a href='http://homepages.inf.ed.ac.uk/wadler/'&gt;beards&lt;/a&gt; and &lt;a href='http://research.microsoft.com/en-us/people/simonpj/'&gt;sandals&lt;/a&gt;) developing the tools and theories behind FP, and spawned the famous &lt;a href='http://en.wikipedia.org/wiki/ICFP_Programming_Contest'&gt;ICFP Programming Contest&lt;/a&gt;. The modern ICFP, however, also caters to the practical industry practitioner at all levels of knowledge, and this blog post is meant to introduce you to what to expect this year.&lt;/p&gt;

&lt;p&gt;ICFP 2012 is a week-long &lt;a href='http://www.icfpconference.org/icfp2012/'&gt;conference&lt;/a&gt; on September 9-15th, held in beautiful Copenhagen. The theory-oriented workshops are held just before the main event on Sunday, on topics such as &lt;a href='http://workshops.inf.ed.ac.uk/xldi2012/'&gt;cross-model&lt;/a&gt;, &lt;a href='http://www.wgp-sigplan.org/2012'&gt;generic&lt;/a&gt; and &lt;a href='http://hope2012.mpi-sws.org'&gt;higher-order&lt;/a&gt; programming. The main conference lasts three days, with a &lt;a href='http://www.icfpconference.org/icfp2012/program.html'&gt;combination&lt;/a&gt; of academic papers and experience reports that are formally published by the ACM (see my &lt;a href='http://anil.recoil.org/papers/2010-icfp-xen.pdf'&gt;experience report&lt;/a&gt; or a &lt;a href='http://thomas.gazagnaire.org/pub/GH09.pdf'&gt;Xenstored full paper&lt;/a&gt; for two Xen-related publications).&lt;/p&gt;

&lt;p&gt;The main conference finishes mid-week, and the focus switches to more informal, interactive workshops that are relevant to the FP practitioner. The &lt;a href='#icfpreg'&gt;registration system&lt;/a&gt; lets you buy a day pass and attend any combination, so here&amp;#8217;s a list that I&amp;#8217;ve come up, along with &amp;#8220;who&amp;#8221; it is intended for. Needless to say, these are my personal views (although I&amp;#8217;m co-chairing CUFP and the OCaml Workshop, and any mistakes there would be bad!).&lt;/p&gt;

&lt;h2 id='commercial_users_of_functional_programming_'&gt;Commercial Users of Functional Programming (&lt;a href='http://cufp.org/conference/schedule'&gt;CUFP&lt;/a&gt;)&lt;/h2&gt;

&lt;p&gt;CUFP has been going since &lt;a href='http://cufp.org/archive/2004/main.html'&gt;2004&lt;/a&gt;, acting as a voice for commercial users of functional programming languages and technology. CUFP is the biggest workshop at ICFP and spread over &lt;a href='http://cufp.org/conference/schedule/2012'&gt;the last three days&lt;/a&gt; of the conference week.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Never done any Functional Programming before&lt;/em&gt;: For the first time, CUFP offers day-long tutorials for complete beginners to functional programming. You can spend a full day learning the basics of &lt;a href='http://cufp.org/conference/sessions/2012/scala-primer-heiko-seeberger-typesafe'&gt;Scala&lt;/a&gt; or two days on &lt;a href='http://cufp.org/conference/sessions/2012/introductory-haskell-concurrent-haskell-jeremy-gib'&gt;Haskell&lt;/a&gt; (including concurrency and multicore). These tutorials are separate events with their own &lt;a href='#icfpreg'&gt;registrations&lt;/a&gt; so you can attend just them if you wish, and still meet the other attendees during the regular breaks and evening events.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;em&gt;Done some FP, and want to improve or learn a new language&lt;/em&gt;: There are half-day tutorials that are more focussed on specific topics: real-world &lt;a href='http://cufp.org/conference/sessions/2012/t1-real-world-ocaml-anil-madhavapeddy-university-c'&gt;OCaml&lt;/a&gt; (by me and Yaron!), &lt;a href='http://cufp.org/conference/sessions/2012/t4-hands-real-world-clojure-lau-jensen-best-class-'&gt;Clojure&lt;/a&gt; and &lt;a href='http://cufp.org/conference/sessions/2012/functional-concepts-real-world-f-tomas-petricek-un'&gt;F#&lt;/a&gt;, and popular web frameworks in &lt;a href='http://cufp.org/conference/sessions/2012/t2-erlang-web-frameworks-steve-vinoski-basho-techn'&gt;Erlang&lt;/a&gt; and &lt;a href='http://cufp.org/conference/sessions/2012/t3-haskell-lazy-web-developer-introduction-happsta'&gt;Haskell&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;em&gt;There&amp;#8217;s safety in crowds&lt;/em&gt;: &lt;a href='http://anil.recoil.org/images/icfp2011-4.jpg'&gt;&lt;img width='120' align='right' src='http://anil.recoil.org/images/icfp2011-4-thumb.jpg' alt='Team Twitter talking about Scala at CUFP 2011' /&gt;&lt;/a&gt;The final day of CUFP (on Saturday 15th) is a full day of experience reports from industry speakers who have applied FP techniques to their day-to-day work. These talks are not intended to be deeply technical, but instead reflect on the social and engineering challenges around integrating a new (and often risky) technology into an existing business. The sessions &lt;a href='http://cufp.org/conference/schedule'&gt;this year&lt;/a&gt; are diverse, with talks from Citrix on client-side cloud computing, on building NoSQL databases, and a number of talks on biotech (&lt;a href='http://cufp.org/conference/sessions/2012/ashish-agarwal-nyu-functional-big-data-genomics'&gt;bigdata&lt;/a&gt;, &lt;a href='http://cufp.org/conference/sessions/2012/adam-granicz-intellifactory-developing-f-bioinform'&gt;visualisation&lt;/a&gt; and &lt;a href='http://cufp.org/conference/sessions/2012/stefan-wehr-factis-research-developing-medical-sof'&gt;medical software&lt;/a&gt;), developing &lt;a href='http://cufp.org/conference/sessions/2012/sebastian-egner-entelios-functional-programs-conne'&gt;real-time&lt;/a&gt; and &lt;a href='http://cufp.org/conference/sessions/2012/kevin-lynagh-keming-labs-clojure-ipad-analytics-da'&gt;offline&lt;/a&gt; analytics for national power grids, and even using FP to write software that runs directly on &lt;a href='http://cufp.org/conference/sessions/2012/peter-braam-parallel-scientific-awesome-haskell-fp'&gt;FPGAs&lt;/a&gt; (including directly on a new 10GBs switch from &lt;a href='http://aristanetworks.com'&gt;Arista networks&lt;/a&gt;). We really try to make this talk session a balanced view of the upsides and downsides of using FP, and encourage speakers to relate what went &lt;em&gt;wrong&lt;/em&gt; as well as right in their experiences.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;em&gt;CTO/executive, aka &amp;#8220;schmoozing&amp;#8221;&lt;/em&gt;: A huge part of CUFP is the great networking between engineers and academics (with job-hunting grad students thrown into the mix). There are regular breaks which are full of animated conversations, and we are planning an industrial reception where vendors can show off their wares (either on Thursday or Friday) where you find commercial support, or recruit bright graduate students from top schools across the world. The breaks are also a chance to corner your favourite language hacker-professor and make them aware of your particular needs!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;m co-chairing CUFP this year along with &lt;a href='http://www.deinprogramm.de/sperber/'&gt;Michael Sperber&lt;/a&gt;, so feel free to direct any questions you have about it to us, and see below for &lt;a href='#icfpreg'&gt;registration information&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='language_workshops'&gt;Language Workshops&lt;/h2&gt;

&lt;p&gt;Some of the bigger communities have &lt;a href='http://www.icfpconference.org/icfp2012/affiliated.html'&gt;day-long workshops&lt;/a&gt; which are a combination of short presentations and regular breaks for discussions. If you are using (or just considering the use of) these languages, then these are a good way to meet all the right people who could help you with your efforts.&lt;/p&gt;

&lt;h3 id='ocaml_and_ml'&gt;OCaml and ML&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;m co-chairing the first &lt;a href='http://oud.ocaml.org'&gt;OCaml Users and Developers&lt;/a&gt; workshop on Friday (Sep 14th). This event has traditionally been run in Paris in &lt;a href='coil.org/2011/04/15/ocaml-users-group.html'&gt;past years&lt;/a&gt;, but we decided it was getting big enought to run alongside ICFP. The &lt;a href='http://cufp.org/conference/sessions/2012/peter-braam-parallel-scientific-awesome-haskell-fp'&gt;talk schedule&lt;/a&gt; is a mix of experience reports and pratical new toolchain developments. There will be talks on all the latest development tools (memory profiling, concurrent programming), standard library efforts (&lt;a href='https://bitbucket.org/yminsky/ocaml-core'&gt;Core&lt;/a&gt;, &lt;a href='http://github.com/OCamlPro/opam'&gt;OPAM&lt;/a&gt; packaging), as well as experience reports (the &lt;a href='http://arakoon.org'&gt;Arakoon k/v store&lt;/a&gt;, &lt;a href='http://www.xen.org/products/cloudxen.html'&gt;Xen Cloud&lt;/a&gt;, and building &lt;a href='http://blog.ashimagroup.net/2011/04/22/exploring-the-moon-with-webgl-and-ocaml/'&gt;3D WebGL engines for NASA&lt;/a&gt;, among others). The hot topic at this workshop is the emerging consensus on building a more integrated OCaml Platform that acts as a stable base for larger applications, and the state-of-the-world talks from Xavier Leroy, Yaron Minsky and Fabrice le Fessant will no doubt kick off heated discussions that will go on late into dinner (last year, we all ended up in a very fine Tokyo restaurant drinking sake and arguing about GADTs and the global financial crisis).&lt;/p&gt;

&lt;p&gt;OCaml is the most widely used variant of the &lt;a href='http://en.wikipedia.org/wiki/ML_(programming_language)'&gt;ML family&lt;/a&gt;, and the &lt;a href='http://www.lexifi.com/ml2012/'&gt;ML workshop&lt;/a&gt; on the day before (Sep 13) takes a broader view on the theory and implementations of ML. Talks here include the &lt;a href='http://www.lexifi.com/ml2012/abstract_coq.txt'&gt;Coq theorem prover&lt;/a&gt;, efficient implementations of OCaml &lt;a href='http://www.lexifi.com/ml2012/abstract_9.txt'&gt;running on the JVM&lt;/a&gt;, &lt;a href='http://www.lexifi.com/ml2012/abstract_10.txt'&gt;multicore-ML&lt;/a&gt;, and experimental extensions to ML-style programming (&lt;a href='http://www.lexifi.com/ml2012/abstract_1.txt'&gt;effect tracking&lt;/a&gt;, &lt;a href='http://www.lexifi.com/ml2012/abstract_3.txt'&gt;model checking&lt;/a&gt;, &lt;a href='http://www.lexifi.com/ml2012/abstract_15.txt'&gt;applicative functors&lt;/a&gt;, and &lt;a href='http://www.lexifi.com/ml2012/abstract_7.txt'&gt;GADTs&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Both of these workshops are convenient to attend over a two-day period (Thu and Fri), and will give you a huge amount of information about the latest developments in the land of ML.&lt;/p&gt;

&lt;h3 id='haskell'&gt;Haskell&lt;/h3&gt;

&lt;p&gt;The Haskell community has been growing &lt;a href='https://plus.google.com/115274377971493973150/posts/SK3urbQxcaf'&gt;rather fast&lt;/a&gt; over the last few years, and so there are two separate days of talks.&lt;/p&gt;

&lt;p&gt;The &lt;a href='http://www.haskell.org/haskell-symposium/2012/'&gt;Haskell Symposium&lt;/a&gt; has formal published proceedings, and consists of a diverse array of research work that has direct implications on the future of Haskell. My personal highlights include the &lt;a href='http://research.microsoft.com/en-us/um/people/simonpj/papers/ndp/haskell12-lippmeier.pdf'&gt;parallel array fusion&lt;/a&gt; and vectorisation for data processing on modern hardware, the intriguing &amp;#8220;Wormhole&amp;#8221; effect-tracking FRP, and &lt;a href='http://www.haskell.org/ghc/docs/7.2.2/html/users_guide/safe-haskell.html'&gt;Safe Haskell&lt;/a&gt; for practical information-flow tracking.&lt;/p&gt;

&lt;p&gt;The second day has the &lt;a href='http://www.haskell.org/haskellwiki/HaskellImplementorsWorkshop/2012'&gt;Haskell Implementors Workshop&lt;/a&gt;, which is a more informal affair aimed at the day-to-day infrastructure and toolchain needs of Haskell. The schedule includes overview talks from the two Simons, and ongoing work on &lt;a href='http://www.haskell.org/haskellwiki/HaskellImplementorsWorkshop/2012/deVries'&gt;distributed programming&lt;/a&gt; and &lt;a href='http://www.haskell.org/haskellwiki/HaskellImplementorsWorkshop/2012/Stutterheim'&gt;Javascript compilation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So if you are after a broad overview of Haskell then attend the Symposium, and if you wish to join the Haskell Hogwarts and start compiler hacking, then the implementors workshop will have all the right people to help you out.&lt;/p&gt;

&lt;h3 id='erlang'&gt;Erlang&lt;/h3&gt;

&lt;p&gt;The &lt;a href='http://www.cse.chalmers.se/~rjmh/EWCFP.html'&gt;Erlang workshop&lt;/a&gt; at ICFP has been running for eleven years now, and tends to be a combination of big projects and work-in-progress reports. This year has the latest on porting Erlang to use &lt;a href='http://www.softlab.ntua.gr/~gtsiour/files/erllvm_pres-20111107.pdf'&gt;LLVM&lt;/a&gt; for high-performance computing, as well as experience reports on scalability testing and the widely-used &lt;a href='http://wiki.basho.com'&gt;Riak&lt;/a&gt; distributed database. Despite my prelediction towards static typing, Erlang is a language that I keep intending to make bigger use of, so I plan to drop into this session for sure.&lt;/p&gt;
&lt;table width='90%' align='center'&gt;
&lt;tr&gt;
&lt;td width='30%' class='bimg'&gt;&lt;a href='http://anil.recoil.org/images/icfp2011-1.jpg'&gt;&lt;img width='120' border='0' src='http://anil.recoil.org/images/icfp2011-1-thumb.jpg' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Last year we had to learn Japanese, the hardest functional language&lt;/i&gt;&lt;/td&gt;
&lt;td width='30%' class='bimg'&gt;&lt;a href='http://anil.recoil.org/images/icfp2011-2.jpg'&gt;&lt;img width='120' border='0' src='http://anil.recoil.org/images/icfp2011-2-thumb.jpg' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;We also made a lot of new local friends&lt;/i&gt;&lt;/td&gt;
&lt;td width='30%' class='bimg'&gt;&lt;a href='http://anil.recoil.org/images/icfp2011-3.jpg'&gt;&lt;img width='120' border='0' src='http://anil.recoil.org/images/icfp2011-3-thumb.jpg' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Luckily, the weather made us feel at home though&lt;/i&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;a name='icfpreg'&gt;&amp;nbsp;&lt;/a&gt;
&lt;h2 id='registration'&gt;Registration&lt;/h2&gt;

&lt;p&gt;This has been a whirlwind tour of the ICFP week (or rather, me writing this down while planning my own schedule). The early registration deadline is &lt;em&gt;next week&lt;/em&gt; (Aug 9th), and the &lt;b&gt;&lt;a href='http://www.icfpconference.org/icfp2012/registration.html'&gt;online registration&lt;/a&gt;&lt;/b&gt; has all the details of the full schedule and day prices. There is also &lt;a href='http://www.icfpconference.org/icfp2012/local.html'&gt;local information&lt;/a&gt; about where to stay and visit in Copenhagen, if you want to take a late-summer break while making the trip.&lt;/p&gt;

&lt;p&gt;Something worth noting is that all of this is run under the auspices of the ACM by volunteers, which accounts for the somewhat chaotic spread of information across all the websites. We&amp;#8217;ve tried to demystify the CUFP process &lt;a href='http://cufp.org/cufp-2012-registration'&gt;here&lt;/a&gt;, but &lt;em&gt;please&lt;/em&gt; get in touch with any of the organisers if you are confused and want some help. We always welcome volunteer offers too, and the first round of drinks is on me for anyone who helps out during the week!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Dreaming of an ARM OCaml</title>
   <link href="http://anil.recoil.org/2012/02/25/dreamplug-debian-and-ocaml.html"/>
   <updated>2012-02-25T00:00:00+00:00</updated>
   <id>http://anil.recoil.org/2012/02/25/dreamplug-debian-and-ocaml</id>
   <content type="html">&lt;a title='dreamplug by tlamer, on Flickr' href='http://www.flickr.com/photos/tlamer/5693063642/'&gt;&lt;img width='200' align='right' src='http://farm6.staticflickr.com/5230/5693063642_47aa7c4c99.jpg' height='134' alt='dreamplug' /&gt;&lt;/a&gt;
&lt;p&gt;I&amp;#8217;ve been meaning to play with &lt;a href='http://www.plugcomputer.org/'&gt;Plug Computers&lt;/a&gt; for some time now, as I need a low-power embedded system around the house. I recently bought a &lt;a href='http://soekris.com/products/net6501.html'&gt;Soekris Net6501&lt;/a&gt; (a pretty powerful Intel CPU, that even has VT support), but had annoying &lt;a href='http://marc.info/?l=soekris-tech&amp;amp;m=132915532912206&amp;amp;w=2'&gt;issues&lt;/a&gt; getting it working reliably. I ordered an ARM-based &lt;a href='http://www.newit.co.uk/shop/products.php?cat=21'&gt;Dreamplug&lt;/a&gt; as an alternative (and as a bonus, the Dreamplug is 6x cheaper than the Soekris!). Here are my notes on getting it to work.&lt;/p&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aside from the Dreamplug itself, make sure you order the optional JTAG module. This provides a serial console that is essential to getting any development done with it.&lt;/li&gt;

&lt;li&gt;I also grabbed the extra 16GB Class 10 SLC SD Card, to act as my home directory.&lt;/li&gt;

&lt;li&gt;You will also need another functional system running Debian (or a VM on your Mac; whatever is easiest). The JTAG drivers for the USB serial are easiest to get running on Linux.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Dreamplug arrived with a working installation, but running the absolutely ancient Debian Lenny. A dist-upgrade through to Wheezy led to bricking it almost immediately, and so I did a fresh installation from scratch.&lt;/p&gt;

&lt;p&gt;For a fresh installation, place a USB stick of suitable size (greater than 2GB is best) into your functional Debian installation. Then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Marvell bootloader boots from a VFAT partition, so you will need two partitions. The first should be a small &lt;code&gt;fat16&lt;/code&gt; (I picked 150MB) and the remainder an &lt;code&gt;ext3&lt;/code&gt; partition for Linux itself. There are good instructions available on the &lt;a href='https://trac.torproject.org/projects/tor/wiki/doc/DebianDreamPlug'&gt;Tor/Dreamplug&lt;/a&gt; wiki which show you how to do this.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;I grabbed the latest kernel (at this time, 3.2.7) from &lt;a href='http://sheeva.with-linux.com/sheeva/3/3.2/3.2.7/'&gt;with-linux&lt;/a&gt;, and installed it with the following commands (assuming your USB stick is &lt;code&gt;/dev/sdb&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='sh'&gt;	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo mount /dev/sdb1 /mnt
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo cp uImage /mnt
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo umount /mnt
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You now need to use &lt;code&gt;debootstrap&lt;/code&gt; to install a fresh root image. Because it is ARM and your main PC is probably an x86, you will need to setup the QEMU CPU emulator. An extremely cool feature of QEMU is that it can do &lt;a href='http://wiki.debian.org/QemuUserEmulation'&gt;transparent emulation&lt;/a&gt; of foreign binaries, so you can chroot directly into the ARM filesystem and run commands as if they were x86. The &lt;code&gt;qemu-deboostrap&lt;/code&gt; command will take care of this for you, if you perform the steps below (again, assuming your USB stick is &lt;code&gt;/dev/sdb&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='sh'&gt;	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo apt-get install qemu-user-static debootstrap
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo mount /dev/sdb2 /mnt
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo mkdir -p /mnt/usr/bin
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo cp /usr/bin/qemu-arm-static /mnt/usr/bin/
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo qemu-debootstrap --arch&lt;span class='o'&gt;=&lt;/span&gt;armel wheezy http://ftp.uk.debian.org/debian/
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Now grab the kernel modules from the same place as your uImage (for 3.2.7, from &lt;a href='http://sheeva.with-linux.com/sheeva/3/3.2/3.2.7/sheeva-3.2.7-Modules.tar.gz'&gt;here&lt;/a&gt;). Then, chroot into your fresh installation and untar them.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='sh'&gt;	&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /mnt
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo tar -zxvf ~/sheeva-3.2.7-Modules.tar.gz
	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo chroot /mnt
	&lt;span class='nv'&gt;$ &lt;/span&gt;depmod -a
	&lt;span class='c'&gt;# edit /etc/network/interfaces&lt;/span&gt;
	&lt;span class='c'&gt;# edit /etc/resolv.conf&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The wireless setup involves some extremely crap firmware which relentlessly kernel panicked for me, so I just disabled it by adding the following to &lt;code&gt;/etc/modprobe.d/dpwifiap.conf&lt;/code&gt;, as I only want wired access:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='sh'&gt;	blacklist libertas
	blacklist libertas_sdio
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;From there on, put the USB stick into the Dreamplug, and follow the rest of the boot instructions from the &lt;a href='https://trac.torproject.org/projects/tor/wiki/doc/DebianDreamPlug'&gt;Tor wiki&lt;/a&gt; to interact with the Marvell BIOS and boot from the USB stick. I copied the contents of the USB stick onto the internal MicroSD, and it all boots standalone now.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='ocaml_on_arm'&gt;OCaml on ARM&lt;/h2&gt;

&lt;p&gt;One of the reasons I wanted an ARM-based setup is to experiment with the OCaml native code generation. &lt;a href='http://www.home.unix-ag.org/bmeurer/index.html'&gt;Benedikt Meurer&lt;/a&gt; has been doing some excellent work on &lt;a href='http://old.nabble.com/New-ARM-backend-merged-into-trunk-td33262083.html'&gt;improving code generation&lt;/a&gt; for embedded systems, including support for 16-bit Thumb code, exception backtraces, and dynamic linking and profiling.&lt;/p&gt;

&lt;p&gt;Once Linux was up and running, compiling up the latest ocaml-trunk was straightforward.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;	&lt;span class='nv'&gt;$ &lt;/span&gt;sudo apt-get install build-essential git
	&lt;span class='nv'&gt;$ &lt;/span&gt;git clone http://github.com/OCamlPro/ocp-ocaml svn-trunk
	&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;ocp-ocaml
	&lt;span class='nv'&gt;$ &lt;/span&gt;./configure &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; make world opt opt.opt install
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This compiles the bytecode and native code compilers, and then compiles them again using the native code generator. This takes a while to do on the poor little ARM CPU. Once that finished, I compiled up a few simple modules and they worked great! Since the trunk of OCaml is a development branch, you may run into a few packaging issues (use the very latest OASIS to regenerate any &lt;code&gt;setup.ml&lt;/code&gt;, and you will need a small patch until &lt;a href='http://caml.inria.fr/mantis/view.php?id=5503'&gt;PR 5503&lt;/a&gt; is applied).&lt;/p&gt;

&lt;p&gt;Incidentally, if anyone is interested in working on a &lt;a href='http://openmirage.org'&gt;Mirage&lt;/a&gt; port to ARM as an internship in the &lt;a href='http://www.cl.cam.ac.uk/research/srg/netos/'&gt;Cambridge Computer Lab&lt;/a&gt;, do get in touch with me&amp;#8230;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Commercial Users of Functional Programming 2011 Schedule</title>
   <link href="http://anil.recoil.org/2011/08/09/cufp2011-schedule.html"/>
   <updated>2011-08-09T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2011/08/09/cufp2011-schedule</id>
   <content type="html">&lt;!-- /#content-top --&gt;&lt;div id='content-area'&gt;
&lt;div class='view view-Schedule view-id-Schedule view-display-id-page_1 view-dom-id-29'&gt;
&lt;div class='view-header'&gt;
&lt;p&gt;The CUFP 2011 schedule is now &lt;a href='http://cufp.org/conference/schedule/2011'&gt;available&lt;/a&gt; and the &lt;a href='https://regmaster3.com/2011conf/ICFP11/register.php'&gt;conference registration&lt;/a&gt; is open!
The &lt;tt&gt;cufp.org&lt;/tt&gt; website is having a few DNS propagation issues at the moment and is unreachable, so I have replicated the schedule below for
your perusal.  Hope to see lots of new faces in Tokyo!&lt;/p&gt;
&lt;/div&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;h3&gt;September 22nd, &lt;b style='color:black;background-color:#a0ffff'&gt;2011&lt;/b&gt;&lt;/h3&gt;
&lt;br /&gt;
&lt;div class='view view-Schedule-Header view-id-Schedule_Header view-display-id-default view-dom-id-1'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class='view view-Schedule-By-Day view-id-Schedule_By_Day view-display-id-default view-dom-id-6'&gt;
&lt;div class='view-content'&gt;
&lt;table class='views-table cols-4'&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;&lt;th&gt;Speakers&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class='odd views-row-first'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;09:00 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;12:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t1-building-reliable-client-server-applications-er'&gt;
T1: Building Reliable Client-Server Applications in Erlang&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-2'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/francescoc'&gt;Francesco
Cesarini&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Erlang
Solutions Ltd.&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;09:00 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;12:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t2-janestreets-ocaml-core-library'&gt;T2:
JaneStreet's OCaml Core Library&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-3'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/yminsky'&gt;Yaron
Minsky&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Jane
Street&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;02:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;05:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t3-building-functional-os'&gt;T3: Building
a Functional OS&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-4'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/avsm'&gt;Anil
Madhavapeddy&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;University of Cambridge&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class='views-row views-row-2 views-row-even'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/djs55'&gt;David Scott&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Citrix&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class='views-row views-row-3 views-row-odd views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/mort'&gt;Richard
Mortier&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;university of nottingham&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even views-row-last'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;02:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;05:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t4-collaborative-scientific-software'&gt;T4:
Collaborative Scientific Software&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-5'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/ashish'&gt;Ashish
Agarwal&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;New
York University&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;September 23rd, &lt;b style='color:black;background-color:#a0ffff'&gt;2011&lt;/b&gt;&lt;/h3&gt;
&lt;br /&gt;
&lt;div class='view view-Schedule-Header view-id-Schedule_Header view-display-id-default view-dom-id-7'&gt;
&lt;/div&gt;
&lt;div class='view view-Schedule-By-Day view-id-Schedule_By_Day view-display-id-default view-dom-id-12'&gt;
&lt;div class='view-content'&gt;
&lt;table class='views-table cols-4'&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;&lt;th&gt;Speakers&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class='odd views-row-first'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;09:00 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;12:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t5-parallel-programming-haskell-simon-peyton-jones'&gt;
T5: Parallel Programming in Haskell (Simon Peyton Jones, Simon
Marlow, Manuel Chakravarty)&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-8'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/simonpj'&gt;Simon
Peyton-Jones&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Microsoft&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;09:00 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;12:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t6-systems-programming-scala-steven-jenson-marius-'&gt;
T6: Systems Programming in Scala (Steven Jenson, Marius
Eriksen)&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-9'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/marius-eriksen'&gt;Marius
Eriksen&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;02:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;05:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t7-snap-framework-web-applications-haskell-gregory'&gt;
T7: The Snap Framework for web applications in Haskell (Gregory
Collins)&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-10'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='/user/' /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even views-row-last'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;02:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;05:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/t8-f-working-functional-programmer'&gt;T8:
F# for the Working Functional Programmer&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-11'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/msperber'&gt;Michael
Sperber&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Active
Group&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;September 24th, &lt;b style='color:black;background-color:#a0ffff'&gt;2011&lt;/b&gt;&lt;/h3&gt;
&lt;br /&gt;
&lt;div class='view view-Schedule-Header view-id-Schedule_Header view-display-id-default view-dom-id-13'&gt;
&lt;/div&gt;
&lt;div class='view view-Schedule-By-Day view-id-Schedule_By_Day view-display-id-default view-dom-id-28'&gt;
&lt;div class='view-content'&gt;
&lt;table class='views-table cols-14'&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;&lt;th&gt;Speakers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class='odd views-row-first'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;09:00 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;10:00 AM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/keynote-pragmatic-haskell'&gt;Keynote:
Pragmatic Haskell&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-14'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/lennartaugustsson'&gt;Lennart
Augustsson&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Standard Chartered Bank&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;10:00 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;10:30 AM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;Tea Break&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-15'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='/user/' /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;10:30 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;11:00 AM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/theorem-based-derivation-aes-implementation'&gt;
Theorem-based derivation of an AES Implementation&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-16'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/jlaunchbury'&gt;John
Launchbury&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Galois&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;11:00 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;11:30 AM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/discrete-event-simulation-using-erlang'&gt;Discrete
Event Simulation using Erlang&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-17'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/olivier-boudeville'&gt;Mr. Olivier
Boudeville&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;EDF
R&amp;amp;D&lt;/em&gt;, &lt;em&gt;energy utility&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;11:30 AM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;12:00 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/model-based-testing-autosar-automotive-components'&gt;
Model based testing of AUTOSAR automotive components&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-18'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/thomas'&gt;Dr. Thomas
Arts&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;QuviQ&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;12:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;01:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;Lunch Break&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-19'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='/user/' /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;01:30 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;02:00 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/html5-web-application-development-ocaml'&gt;
HTML5 web application development in OCaml&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-20'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/keigoi'&gt;Mr. Keigo
Imai&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;IT
Planning, Inc.&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;02:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;02:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/large-scale-internet-services-scala-twitter'&gt;
Large-scale Internet Services in Scala at Twitter&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-21'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/wilhelm-bierbaum'&gt;Wilhelm
Bierbaum&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class='views-row views-row-2 views-row-even views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/stevejenson'&gt;Steve
Jenson&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;02:30 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;03:00 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/applying-functional-programming-build-platform-ind'&gt;
Applying Functional Programming to Build Platform-Independent
Mobile Applications&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-22'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/agranicz'&gt;Adam
Granicz&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;IntelliFactory&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;03:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;03:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;Tea Break&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-23'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='/user/' /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;03:30 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;04:00 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/fourteen-days-haskell-real-time-programming-projec'&gt;
Fourteen Days of Haskell: A Real Time Programming Project in Real
Time&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-24'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/gregorywright'&gt;Gregory
Wright&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Alcatel-Lucent&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;04:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;04:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/disco-using-erlang-implement-mapreduce-nokia'&gt;
Disco: using Erlang to implement Mapreduce, Nokia&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-25'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/jaredflatow'&gt;Jared
Flatow&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Erlang&lt;/em&gt;, &lt;em&gt;Nokia&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class='views-row views-row-2 views-row-even'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/prashanthmundkur'&gt;Prashanth
Mundkur&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Erlang&lt;/em&gt;, &lt;em&gt;Nokia&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class='views-row views-row-3 views-row-odd views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/tuulos'&gt;Ville
Tuulos&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Nokia
Research&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='odd'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;04:30 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;05:00 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/functional-mzscheme-dsls-game-development'&gt;
Functional mzScheme DSLs in Game Development&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-26'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/danliebgold'&gt;Dan
Liebgold&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Naughty Dog Inc.&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class='even views-row-last'&gt;
&lt;td class='views-field views-field-field-sesion-time-value active'&gt;
&lt;span class='date-display-single'&gt;&lt;span class='date-display-start'&gt;05:00 PM&lt;/span&gt; &lt;span class='date-display-separator'&gt;-&lt;/span&gt; &lt;span class='date-display-end'&gt;05:30 PM&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td class='views-field views-field-title'&gt;&lt;a href='http://cufp.org/conference/sessions/2011/ocaml-and-acunu-experience-report'&gt;OCaml
and Acunu Experience Report&lt;/a&gt;&lt;/td&gt;
&lt;td class='views-field views-field-phpcode-1'&gt;
&lt;div class='view view-Speakers view-id-Speakers view-display-id-default view-dom-id-27'&gt;
&lt;div class='view-content'&gt;
&lt;div class='views-row views-row-1 views-row-odd views-row-first'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/andrewbyde'&gt;Andrew
Byde&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Acunu&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class='views-row views-row-2 views-row-even views-row-last'&gt;
&lt;div class='views-field-phpcode'&gt;&lt;span class='field-content'&gt;&lt;a href='http://cufp.org/users/tomwilkie'&gt;Tom
Wilkie&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class='views-field-tid'&gt;&lt;span class='field-content'&gt;&lt;em&gt;Acunu&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>DataCaml - a first look at distributed dataflow programming in OCaml</title>
   <link href="http://anil.recoil.org/2011/06/18/datacaml-with-ciel.html"/>
   <updated>2011-06-18T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2011/06/18/datacaml-with-ciel</id>
   <content type="html">&lt;p&gt;Distributed programming frameworks like &lt;a href='http://wiki.apache.org/hadoop'&gt;Hadoop&lt;/a&gt; and &lt;a href='http://research.microsoft.com/en-us/projects/dryad/'&gt;Dryad&lt;/a&gt; are popular for performing computation over large amounts of data. The reason is programmer convenience: they accept a query expressed in a simple form such as &lt;a href='http://wiki.apache.org/hadoop/HadoopMapReduce'&gt;MapReduce&lt;/a&gt;, and automatically take care of distributing computation to multiple hosts, ensuring the data is available at all nodes that need it, and dealing with host failures and stragglers.&lt;/p&gt;

&lt;p&gt;A major limitation of Hadoop and Dryad is that they are not well-suited to expressing &lt;a href='http://en.wikipedia.org/wiki/Iterative_method'&gt;iterative algorithms&lt;/a&gt; or &lt;a href='http://en.wikipedia.org/wiki/Dynamic_programming'&gt;dynamic programming&lt;/a&gt; problems. These are very commonly found patterns in many algorithms, such as &lt;a href='http://en.wikipedia.org/wiki/K-means_clustering'&gt;k-means clustering&lt;/a&gt;, &lt;a href='http://en.wikipedia.org/wiki/Binomial_options_pricing_model'&gt;binomial options pricing&lt;/a&gt; or &lt;a href='http://en.wikipedia.org/wiki/Smith–Waterman_algorithm'&gt;Smith Waterman&lt;/a&gt; for sequence alignment.&lt;/p&gt;

&lt;p&gt;Over in the SRG in Cambridge, &lt;a href='http://www.cl.cam.ac.uk/research/srg/netos/ciel/who-we-are/'&gt;we&lt;/a&gt; developed a Turing-powerful distributed execution engine called &lt;a href='http://www.cl.cam.ac.uk/research/srg/netos/ciel/'&gt;CIEL&lt;/a&gt; that addresses this. The &lt;a href='http://anil.recoil.org/papers/2011-nsdi-ciel.pdf'&gt;NSDI 2011&lt;/a&gt; paper describes the system in detail, but here&amp;#8217;s a shorter introduction.&lt;/p&gt;

&lt;h2 id='the_ciel_execution_engine'&gt;The CIEL Execution Engine&lt;/h2&gt;

&lt;p&gt;CIEL consists of a master coordination server and workers installed on every host. The engine is job-oriented: a job consists of a graph of tasks which results in a deterministic output. CIEL tasks can run in any language and are started by the worker processes as needed. Data flows around the cluster in the form of &lt;em&gt;references&lt;/em&gt; that are fed to tasks as dependencies. Tasks can publish their outputs either as &lt;em&gt;concrete&lt;/em&gt; references if they can finish the work immediately or as a &lt;em&gt;future&lt;/em&gt; reference. Additionally, tasks can dynamically spawn more tasks and delegate references to them, which makes the system Turing-powerful and suitable for iterative and dynamic programming problems where the task graph cannot be computed statically.&lt;/p&gt;

&lt;p&gt;The first iteration of CIEL used a domain-specific language called &lt;a href='http://anil.recoil.org/papers/2011-nsdi-ciel.pdf'&gt;Skywriting&lt;/a&gt; to coordinate how tasks should run across a cluster. Skywriting is an interpreted language that is &amp;#8220;native&amp;#8221; to CIEL, and when it needs to block it stores its entire execution state inside CIEL as a continuation. &lt;a href='http://www.cl.cam.ac.uk/~dgm36/'&gt;Derek Murray&lt;/a&gt; has written a blog post &lt;a href='http://www.syslog.cl.cam.ac.uk/2011/04/06/ciel/'&gt;explaining this in more detail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More recently, we have been working on eliminating the need for Skywriting entirely, by adding direct support for CIEL into languages such as &lt;a href='http://www.stackless.com/'&gt;Python&lt;/a&gt;, Java, &lt;a href='http://www.scala-lang.org/'&gt;Scala&lt;/a&gt;, and the main subject of this post &amp;#8211; &lt;a href='http://caml.inria.fr'&gt;OCaml&lt;/a&gt;. It works via libraries that communicate with CIEL to spawn tasks, publish references, or suspend itself into the cluster to be woken up when a future reference is completed.&lt;/p&gt;

&lt;h2 id='datacaml_api'&gt;DataCaml API&lt;/h2&gt;

&lt;p&gt;Rather than go into too much detail about the innards of CIEL, this post describes the OCaml API and gives some examples of how to use it. The simplest interface to start with is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;deref&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The type &lt;code&gt;&amp;#39;a ref&lt;/code&gt; represents a CIEL reference. This data might not be immediately present on the current node, and so must be dereferenced using the &lt;code&gt;deref&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;If the reference has been completed, then the OCaml value is unmarshalled and returned. If it is not present, then the program needs to wait until the computation involving the reference has completed elsewhere. The future reference might contain a large data structure and be on another host entirely, and so we should serialise the program state and spawn a task that is dependent on the future&amp;#8217;s completion. This way, CIEL can resume execution on whatever node finished that computation, avoiding the need to move data across the network.&lt;/p&gt;

&lt;p&gt;Luckily, we do not need to serialise the entire heap to suspend the program. DataCaml uses the &lt;a href='http://okmij.org/ftp/continuations/implementations.html'&gt;delimcc&lt;/a&gt; delimited continuations library to walk the stack and save only the subset required to restart this particular task. Delimcc abstracts this in the form a &amp;#8220;restartable exception&amp;#8221; that supplies a closure which can be called later to resume the execution, as if the exception had never happened. Delimcc supports serialising this closure to an output channel, which you can read about in Oleg&amp;#8217;s &lt;a href='http://okmij.org/ftp/continuations/caml-shift.pdf'&gt;paper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So how do we construct references? Lets fill in more of the interface:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Ciel&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;struct&lt;/span&gt;
	  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;deref&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;spawn&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='kt'&gt;list&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;spawn&lt;/code&gt; function accepts a closure and an argument, and returns a future of the result as a reference. The &lt;code&gt;run&lt;/code&gt; function begins the execution of a job, with the first parameter taking some &lt;code&gt;string arguments&lt;/code&gt; and returning an &lt;code&gt;&amp;#39;a&lt;/code&gt; value. We also supply a pretty-printer second argument to convert the &lt;code&gt;&amp;#39;a&lt;/code&gt; into a string for returning as the result of the job (this can actually be any JSON value in CIEL, and just simplified here).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;r1&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;spawn&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;arg1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
  	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;r2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;spawn&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;deref&lt;/span&gt; &lt;span class='n'&gt;r1&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;arg1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
	&lt;span class='n'&gt;deref&lt;/span&gt; &lt;span class='n'&gt;r2&lt;/span&gt; 
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We first spawn a function &lt;code&gt;r1&lt;/code&gt; which simply adds 5 to the job argument. A job in CIEL is &lt;em&gt;lazily scheduled&lt;/em&gt;, so this marshals the function to CIEL, creates a future, and returns immediately. Next, the &lt;code&gt;r2&lt;/code&gt; function spawns a task which also adds 5, but to the dereferenced value of &lt;code&gt;r1&lt;/code&gt;. Again, it is not scheduled yet as the return reference has not been dereferenced.&lt;/p&gt;

&lt;p&gt;Finally, we attempt to dereference &lt;code&gt;r2&lt;/code&gt;, which causes it be scheduled on a worker. While executing, it will try to dereference &lt;code&gt;r1&lt;/code&gt; that will schedule it, and all the tasks will run to completion.&lt;/p&gt;

&lt;p&gt;Programming language boffins will recognise that this interface is very similar to &lt;a href='http://www.ps.uni-saarland.de/alice/'&gt;AliceML&lt;/a&gt;&amp;#8217;s concept of &lt;a href='http://www.ps.uni-saarland.de/alice/manual/futures.html'&gt;lazy futures&lt;/a&gt;. The main difference is that it is implemented as a pure OCaml library, and uses a general-purpose distributed engine that can also work with other languages.&lt;/p&gt;

&lt;h2 id='streaming_references'&gt;Streaming References&lt;/h2&gt;

&lt;p&gt;The references described so far only have two states: they are either concrete or futures. However, there are times when a task can progressively accept input and make forward progress. For these situations, references can also be typed as &lt;em&gt;opaque&lt;/em&gt; references that are accessed via &lt;code&gt;in_channel&lt;/code&gt; and &lt;code&gt;out_channel&lt;/code&gt;, as networks are:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;opaque_ref&lt;/span&gt;

	&lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;spawn_ref&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;opaque_ref&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;opaque_ref&lt;/span&gt;
	&lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;output&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;?&lt;/span&gt;&lt;span class='n'&gt;stream&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;bool&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;?&lt;/span&gt;&lt;span class='n'&gt;pipe&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;bool&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;out_channel&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;opaque_ref&lt;/span&gt;
	&lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;input&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;in_channel&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;opaque_ref&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This interface is a lower-level version of the previous one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;spawn_ref&lt;/code&gt; creates a lazy future as before, but the type of references here is completely opaque to the program.&lt;/li&gt;

&lt;li&gt;Inside a spawned function, &lt;code&gt;output&lt;/code&gt; is called with a closure that accepts an &lt;code&gt;out_channel&lt;/code&gt;. The &lt;code&gt;stream&lt;/code&gt; argument informs CIEL that a dependent task can consume the output before it is completed, and &lt;code&gt;pipe&lt;/code&gt; forms an even more closely coupled shared-memory connection (requiring the tasks to be scheduled on the same host). Piping is more efficient, but will require more work to recover from a fault, and so using it is left to the programmer to decide.&lt;/li&gt;

&lt;li&gt;The &lt;code&gt;input&lt;/code&gt; function is used by the receiving task to parse the input as a standard &lt;code&gt;in_channel&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CIEL engine actually supports multiple concurrent input and output streams to a task, but I&amp;#8217;ve just bound it as a single version for now while the bindings find their feet. Here&amp;#8217;s an example of how streaming references can be used:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;x_ref&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;spawn_ref&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	  &lt;span class='n'&gt;output&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='n'&gt;stream&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='bp'&gt;true&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;oc&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;to&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
	      &lt;span class='nn'&gt;Unix&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sleep&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
	      &lt;span class='n'&gt;fprintf&lt;/span&gt; &lt;span class='n'&gt;oc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;%d&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;%!&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
	    &lt;span class='k'&gt;done&lt;/span&gt;
	  &lt;span class='o'&gt;)&lt;/span&gt;
	&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;y_ref&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;spawn_ref&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	  &lt;span class='n'&gt;input&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;ic&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	    &lt;span class='n'&gt;output&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='n'&gt;stream&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='bp'&gt;true&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;oc&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	      &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;to&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
	        &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;line&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;input_line&lt;/span&gt; &lt;span class='n'&gt;ic&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
	        &lt;span class='n'&gt;fprintf&lt;/span&gt; &lt;span class='n'&gt;oc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;LINE=%s&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;%!&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;line&lt;/span&gt;
	      &lt;span class='k'&gt;done&lt;/span&gt;
	    &lt;span class='o'&gt;)&lt;/span&gt;
	  &lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;x_ref&lt;/span&gt;
	&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We first spawn an &lt;code&gt;x_ref&lt;/code&gt; which pretends to do 5 seconds of work by sleeping and outputing a number. This would of course be heavy number crunching in a real program. The &lt;code&gt;y_ref&lt;/code&gt; then inputs this stream, and outputs its own result by prepending a string to each line.&lt;/p&gt;

&lt;h2 id='try_it_out'&gt;Try it out&lt;/h2&gt;

&lt;p&gt;If you are interested in a more real example, then read through the &lt;a href='https://github.com/avsm/ciel/blob/master/src/ocaml/binomial.ml'&gt;binomial options&lt;/a&gt; calculator that uses streaming references to parallelise a dynamic programming problem (this would be difficult to express in MapReduce). On my Mac, I can run this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;check out CIEL from from Derek&amp;#8217;s &lt;a href='http://github.com/mrry/ciel'&gt;Git repository&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;install all the Python libraries required (see the &lt;code&gt;INSTALL&lt;/code&gt; file) and OCaml libraries (&lt;a href='http://okmij.org/ftp/continuations/implementations.html'&gt;delimcc&lt;/a&gt; and &lt;a href='http://martin.jambon.free.fr/yojson.html'&gt;Yojson&lt;/a&gt;).&lt;/li&gt;

&lt;li&gt;add &lt;code&gt;&amp;lt;repo&amp;gt;/src/python&lt;/code&gt; to your &lt;code&gt;PYTHONPATH&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;in one terminal: &lt;code&gt;./scripts/run_master.sh&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;in another terminal: &lt;code&gt;./scripts/run_worker.sh -n 5&lt;/code&gt; (this allocates 5 execution slots)&lt;/li&gt;

&lt;li&gt;build the OCaml libraries: &lt;code&gt;cd src/ocaml &amp;amp;&amp;amp; make&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;start the binomial options job: &lt;code&gt;./scripts/sw-start-job -m http://localhost:8000 ./src/package/ocaml_binopt.pack&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;there will be a URL printed which shows the execution progress in real-time&lt;/li&gt;

&lt;li&gt;you should see log activity on the worker(s), and a result reference with the answer (&lt;code&gt;10.x&lt;/code&gt;)&lt;/li&gt;

&lt;li&gt;let us know the happy news if it worked or sad news if something broke&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='discussion'&gt;Discussion&lt;/h2&gt;

&lt;p&gt;The DataCaml bindings outlined here provide an easy way to write distributed, fault-tolerant and cluster-scheduled jobs in OCaml. The current implementation of the engine is aimed at cluster computation, but &lt;a href='http://www.cl.cam.ac.uk/~ms705'&gt;Malte&lt;/a&gt; has been working on &lt;a href='http://www.cl.cam.ac.uk/~ms705/pub/papers/2011-ciel-sfma.pdf'&gt;condensing CIEL onto multicore hardware&lt;/a&gt;. Thus, this could be one approach to &amp;#8216;solving the OCaml multicore problem&amp;#8217; for problems that fit nicely into the dataflow paradigm.&lt;/p&gt;

&lt;p&gt;The biggest limitation for using these bindings is that delimited continuation serialisation only works in bytecode. Native code delimcc supports &lt;code&gt;shift/reduce&lt;/code&gt; in the same program, but serialising is problematic since native code continuations contain a C stack, which may have unwrapped integers. One way to work around this is by switching to a monadic approach to dereferencing, but I find delimcc programming more natural (also see &lt;a href='http://www.openmirage.org/wiki/delimcc-vs-lwt'&gt;this discussion&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Another important point is that tasks are lazy and purely functional (remind you of Haskell?). This is essential for reliable fault-tolerance and reproducibility, while allowing individual tasks to run fast, strict and mutable OCaml code. The tasks must remain referentially transparent and idempotent, as CIEL may choose to schedule them multiple times (in the case of faults or straggler correction). Derek has been working on &lt;a href='http://www.cl.cam.ac.uk/~dgm36/publications/2011-murray2011nondet.pdf'&gt;integrating non-determinism into CIEL&lt;/a&gt;, so this restriction may be relaxed soon.&lt;/p&gt;

&lt;p&gt;Finally, these ideas are not limited to OCaml at all, but also apply to Scala, Java, and Python. We have submitted a draft paper dubbed &lt;em&gt;&amp;#8217;&lt;a href='http://www.cl.cam.ac.uk/~ms705/pub/papers/2011-ciel-socc-draft.pdf'&gt;A Polyglot Approach to Cloud Programming&lt;/a&gt;&amp;#8217;&lt;/em&gt; with more details and the ubiquitous evaluation versus Hadoop. There is a really interesting line to explore between low-level &lt;a href='http://en.wikipedia.org/wiki/Message_Passing_Interface'&gt;MPI&lt;/a&gt; coding and high-level MapReduce, and we think CIEL is a useful spot in that design space.&lt;/p&gt;

&lt;p&gt;Incidentally, I was recently hosted by &lt;a href='http://research.nokia.com/'&gt;Nokia Research&lt;/a&gt; in Palo Alto by my friend &lt;a href='http://www.linkedin.com/pub/prashanth-mundkur/6/b44/27'&gt;Prashanth Mundkur&lt;/a&gt;, where they work on the Python/Erlang/OCaml &lt;a href='http://discoproject.org/'&gt;Disco&lt;/a&gt; MapReduce engine. I&amp;#8217;m looking forward to seeing more critical comparisons and discussions of alternatives to Hadoop, from them and others.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks are due to &lt;a href='http://www.cl.cam.ac.uk/~dgm36/'&gt;Derek&lt;/a&gt;, &lt;a href='https://twitter.com/#!/chrissmowton'&gt;Chris&lt;/a&gt; and &lt;a href='http://www.cl.cam.ac.uk/~ms705'&gt;Malte&lt;/a&gt; for answering my incessant CIEL questions while writing this post! Remember that DataCaml is a work in progress and a research prototype, and feedback is most welcome.&lt;/em&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Recoil gets IPv6 at last</title>
   <link href="http://anil.recoil.org/2011/06/08/world-ipv6-day.html"/>
   <updated>2011-06-08T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2011/06/08/world-ipv6-day</id>
   <content type="html">&lt;p&gt;Since it is &lt;a href='http://www.worldipv6day.org/'&gt;World IPv6 Day&lt;/a&gt; today, I decided to update the &lt;tt&gt;recoil.org&lt;/tt&gt; machines to support it.&lt;/p&gt;

&lt;p&gt;The changes required turned out to be very straightforward. Our amazing hosting provider &lt;a href='http://www.bytemark.co.uk'&gt;Bytemark&lt;/a&gt; has been IPv6-ready &lt;a href='http://www.bytemark.co.uk/support/technical_documents/ipv6'&gt;for some time&lt;/a&gt;, and so I just had to reconfigure OpenBSD to add the IPv6 equivalent address as an alias to the network device. This is done by adding a single line to the &lt;code&gt;/etc/hostname.re0&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;inet6 alias 2001:41c8:0010:02ad::1 64&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#8230;and an additional default route in the &lt;code&gt;/etc/mygate&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;fe80::1%re0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;%re0&lt;/code&gt; at the end indicates which network interface to route across, as &lt;code&gt;fe80::1&lt;/code&gt; is a link-local address.&lt;/p&gt;

&lt;p&gt;Then, I had to add an IPv6 &lt;code&gt;AAAA&lt;/code&gt; record in the DNS. We use a hosting provider called &lt;a href='http://www.easydns.org'&gt;EasyDNS&lt;/a&gt; who have support for this in their new &lt;a href='http://helpwiki.easydns.com/index.php/Editing_IPv6_Records'&gt;user interface&lt;/a&gt;. One thing to be aware of is that you must upgrade your domain to their &lt;a href='http://blog.easydns.org/2010/02/01/big-changes-coming-to-easydns/'&gt;new system&lt;/a&gt; if you haven&amp;#8217;t touched the DNS setup for a whole, which took me a while to find out (but they &lt;a href='https://twitter.com/#!/easyDNS/status/78492302615658496'&gt;responded&lt;/a&gt; very quickly on Twitter!).&lt;/p&gt;

&lt;p&gt;Once that was done, I can now check the host record in DNS, and connect to Google over IPv6!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ host -t aaaa www.recoil.org
www.recoil.org is an alias for static.recoil.org.
static.recoil.org is an alias for dark.recoil.org.
dark.recoil.org has IPv6 address 2001:41c8:10:2ad::1

$ ping6 ipv6.google.com
PING6(56=40+8+8 bytes) 2001:41c8:10:2ad::1 --&amp;gt; 2a00:1450:8002::69
16 bytes from 2a00:1450:8002::69, icmp_seq=0 hlim=56 time=13.313 ms
16 bytes from 2a00:1450:8002::69, icmp_seq=1 hlim=56 time=13.165 ms
16 bytes from 2a00:1450:8002::69, icmp_seq=2 hlim=56 time=13.332 ms&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Awesome! One final change is to modify system daemons to also listen on IPv6 in addition to IPv4. I&amp;#8217;ve only changed our &lt;a href='http://wiki.nginx.org/'&gt;nginx&lt;/a&gt; web server so far, by following these IPv6 &lt;a href='http://kovyrin.net/2010/01/16/enabling-ipv6-support-in-nginx/'&gt;instructions&lt;/a&gt;. The OpenBSD ports version of &lt;code&gt;nginx&lt;/code&gt; already has IPv6 support compiled in, so I just added a single line to the configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;listen [::]:80;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since I don&amp;#8217;t have access to any other IPv6 machines, I tested that the website is available by going to the &lt;a href='http://ipv6-test.com/validate.php'&gt;IPv6 website reachability tester&lt;/a&gt;, and typing in &lt;code&gt;www.recoil.org&lt;/code&gt;. And it all worked, and I got this cool little badge to display here&amp;#8230;&lt;/p&gt;
&lt;!-- IPv6-test.com button BEGIN --&gt;&lt;a href='http://ipv6-test.com/validate.php?url=referer'&gt;&lt;img border='0' src='http://ipv6-test.com/button-ipv6-big.png' title='ipv6 ready' alt='ipv6 ready' /&gt;&lt;/a&gt;&lt;!-- IPv6-test.com button END --&gt;</content>
 </entry>
 
 <entry>
   <title>Camel Spotting in Paris</title>
   <link href="http://anil.recoil.org/2011/04/15/ocaml-users-group.html"/>
   <updated>2011-04-15T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2011/04/15/ocaml-users-group</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m at the &lt;a href='https://forge.ocamlcore.org/plugins/mediawiki/wiki/ocaml-meeting/index.php/OCamlMeeting2011'&gt;2011 OCaml Users Group&lt;/a&gt; in Paris, reporting on some splendid talks this year. It looked like around 60-70 people in the room, and I had the pleasure of meeting users all the way from &lt;a href='http://ru.linkedin.com/pub/dmitry-bely/4/955/717'&gt;Russia&lt;/a&gt; to &lt;a href='http://ashishagarwal.org/about/'&gt;New York&lt;/a&gt; as well as all the Europeans!&lt;/p&gt;

&lt;h3 id='js_of_ocaml'&gt;Js_of_ocaml&lt;/h3&gt;

&lt;p&gt;First up was &lt;a href='http://www.lsv.ens-cachan.fr/~chambart/'&gt;Pierre Chambart&lt;/a&gt; talking about the &lt;a href='http://ocsigen.org/js_of_ocaml/'&gt;js_of_ocaml&lt;/a&gt; compiler. It compiles OCaml bytecode directly to Javascript, with few external dependencies. Since the bytecode format changes very rarely, it is simpler to maintain than alternatives (such as Jake Donham&amp;#8217;s &lt;a href='https://github.com/jaked/ocamljs'&gt;ocamljs&lt;/a&gt;) that require patching the compiler tool-chain. Javascript objects are mapped to dynamic OCaml objects via a light-weight &lt;code&gt;##&lt;/code&gt; operator, so you can simply write code like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;window&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;object&lt;/span&gt;
	  &lt;span class='k'&gt;method&lt;/span&gt; &lt;span class='n'&gt;alert&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;js_string&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='n'&gt;meth&lt;/span&gt;
	  &lt;span class='k'&gt;method&lt;/span&gt; &lt;span class='n'&gt;name&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;js_string&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='n'&gt;prop&lt;/span&gt;
	&lt;span class='k'&gt;end&lt;/span&gt;
	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;window&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;window&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
	  &lt;span class='nn'&gt;JS&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nn'&gt;Unsafe&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;variable&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;window&amp;quot;&lt;/span&gt;
	
	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
	  &lt;span class='n'&gt;window&lt;/span&gt;&lt;span class='o'&gt;##&lt;/span&gt;&lt;span class='n'&gt;alert&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt; &lt;span class='n'&gt;window&lt;/span&gt;&lt;span class='o'&gt;##&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
	  &lt;span class='n'&gt;name&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='nn'&gt;Js&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;name&amp;quot;&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Overloading is handled similarly to &lt;a href='http://pyobjc.sourceforge.net/'&gt;PyObjC&lt;/a&gt;, with each parameter combination being mapped into a uniquely named function. &lt;a href='https://github.com/raphael-proust'&gt;Raphael Proust&lt;/a&gt; then demonstrated a cool game he wrote using via &lt;a href='https://github.com/raphael-proust/raphael'&gt;bindings&lt;/a&gt; to the &lt;a href='http://raphaeljs.com/'&gt;Raphael&lt;/a&gt; Javascript vector graphics library. Performance of &lt;code&gt;js_of_ocaml&lt;/code&gt; is good compared to writing it by hand, and they have have quite a few &lt;a href='http://ocsigen.org/js_of_ocaml/doc/1.0.2/manual/performances'&gt;benchmarks&lt;/a&gt; on their website.&lt;/p&gt;

&lt;p&gt;Overall the project looks very usable: the main omissions are Bigarray, no dynlink, no Str (replaced by native regexps), no recursive modules or weak references. None of these missing features seem very critical for the sorts of applications that &lt;code&gt;js_of_ocaml&lt;/code&gt; is intended for.&lt;/p&gt;

&lt;h3 id='ocaml_on_a_pic_ocapic'&gt;OCaml on a PIC (OCAPIC)&lt;/h3&gt;

&lt;p&gt;Next up Phillipe Wang presented something completely different: &lt;a href='http://www.algo-prog.info/ocaml_for_pic/web/index.php'&gt;running OCaml on tiny 8-bit PIC microcontrollers&lt;/a&gt;! These PICs have 4-128Kb of flash (to store the code), and from 256 &lt;em&gt;bytes&lt;/em&gt; to 4 kilobytes. Not a lot of room to waste there. He demonstrated an example with a game with 24 physical push buttons that beat humans at a conference (JFLA).&lt;/p&gt;

&lt;p&gt;It works by translating OCaml bytecode through several stages: &lt;code&gt;ocamlclean&lt;/code&gt; to eliminate dead code in the bytecode (which would be very useful for native code too!), a compression step that does run-length encoding, and then translation to PIC assembly. They have a replacement stop-and-copy GC (150 lines of assembly) and a full collection cycle runs in less than 1.5ms. Integers are 15-bits (with 1 bit reserved) and the block representation is the same as native OCaml. Very cool project!&lt;/p&gt;

&lt;h3 id='framac'&gt;Frama-C&lt;/h3&gt;

&lt;p&gt;We went onto static analysis and &lt;a href='http://www.linkedin.com/pub/julien-signoles/24/5a9/4b4'&gt;Julien Signoles&lt;/a&gt; presented &lt;a href='http://frama-c.com/'&gt;Frama-C&lt;/a&gt;, a powerful static analysis tool for real-world C. It forks the &lt;a href='http://www.eecs.berkeley.edu/~necula/cil/'&gt;CIL&lt;/a&gt; project from Berkeley and adds &lt;a href='http://ocamlgraph.lri.fr/'&gt;ocamlgraph&lt;/a&gt; and GUI support. He demonstrated a simple loop counter plugin to count them in C code, and the homepage has many interesting &lt;a href='http://frama-c.com/plugins.html'&gt;plugins&lt;/a&gt; maintained by the community.&lt;/p&gt;

&lt;p&gt;I hadn&amp;#8217;t realised that CIL was still maintained in the face of &lt;a href='http://clang.llvm.org/'&gt;clang&lt;/a&gt;, so it&amp;#8217;s nice to see it live on as part of Frama-C.&lt;/p&gt;

&lt;h3 id='ocsigen'&gt;Ocsigen&lt;/h3&gt;

&lt;p&gt;The ever-cheerful &lt;a href='http://www.pps.jussieu.fr/~balat/'&gt;Vincent Balat&lt;/a&gt; updated us about the &lt;a href='http://ocsigen.org'&gt;Ocsigen&lt;/a&gt; web framework, including unveiling their exciting new logo! This was written using an amazing &lt;a href='http://ocsigen.org/tutorial/tutorial1'&gt;collaborative editor&lt;/a&gt; that lets users edit in real time.&lt;/p&gt;

&lt;p&gt;Ocsigen is based around &lt;em&gt;services&lt;/em&gt; of type &lt;code&gt;service: parameters -&amp;gt; page&lt;/code&gt;. Services are first-class values, and can be registered dynamically and associated with sessions. The code for the collaborative editor was about 100 lines of code.&lt;/p&gt;

&lt;p&gt;There is a syntax extension to distinguish between client and server side code, and both can be written in the same service (invoking &lt;code&gt;js_of_ocaml&lt;/code&gt; to compile the client code to Javascript). They have bindings to &lt;a href='http://code.google.com/closure/'&gt;Google Closure&lt;/a&gt; in order to provide UI support. There is a really nice &amp;#8220;bus&amp;#8221; service to pass messages between the server and the client, with seamless integration of &lt;a href='http://ocsigen.org/lwt'&gt;Lwt&lt;/a&gt; to hide the details of communication to the browser.&lt;/p&gt;

&lt;p&gt;Ocsigen is looking like a very mature project at this point, and I&amp;#8217;m very keen to integrate it with &lt;a href='http://www.openmirage.org'&gt;Mirage&lt;/a&gt; to specialise the into micro-kernels. A task for the hacking day tomorrow morning I think!&lt;/p&gt;

&lt;h3 id='mirage'&gt;Mirage&lt;/h3&gt;

&lt;p&gt;I talked about &lt;a href='http://www.openmirage.org'&gt;Mirage&lt;/a&gt;, hurrah! Good questions about why we need a block device (and not just use NFS), and I replied that everything is available as the library and the programmer can choose depending on their needs (the core goal of &lt;a href='http://en.wikipedia.org/wiki/Exokernel'&gt;exokernels&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;A highlight for me was lunch where I finally met &lt;a href='http://people.redhat.com/~rjones/'&gt;Richard Jones&lt;/a&gt;, who is one of the other OCaml and cloud hackers out there. Wide ranging conversation about what the cool stuff going in &lt;a href='http://www.linux-kvm.org/page/Main_Page'&gt;KVM&lt;/a&gt; and Red Hat in general. Richard also gave a short talk about how they use OCaml to generate hundreds of thousands of lines of code in &lt;a href='http://libguestfs.org/'&gt;libguestfs&lt;/a&gt;. There are bindings for pretty much every major language, and it is all generated from an executable specification. He notes that &amp;#8220;normal&amp;#8221; programmers love the OCaml type safety without explicit annotations, and that it is a really practical language for the working programmer. The &lt;a href='http://xen.org'&gt;Xen Cloud Platform&lt;/a&gt; also has a similar &lt;a href='https://github.com/xen-org/xen-api/blob/master/ocaml/idl/datamodel.ml'&gt;generator&lt;/a&gt; for XenAPI bindings, so I definitely agree with him about this!&lt;/p&gt;

&lt;h3 id='ocaml_future'&gt;OCaml Future&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://pauillac.inria.fr/~xleroy/'&gt;Xavier &amp;#8220;superstar&amp;#8221; Leroy&lt;/a&gt; then gave an update of OCaml development. Major new features in 3.12.0 are first-class modules, polymorphic recursion, local module opens, and richer operations over module signatures. Version 3.12.1 is coming out soon, with bug fixes (in camlp4 and ocamlbuild mainly), and better performance on x86_64: turns out a new &lt;code&gt;mov&lt;/code&gt; instruction change improves floating point performance on &lt;code&gt;x86_64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;OCaml 3.13 has no release date, but several exciting features are in the pipeline. Firstly, more lightweight first-class modules by permitting some annotations to be inferred by the context, and it introduces patterns to match and bind first-class module values. Much more exciting is support for GADTs (Generalised Algebraic Data Types). This permits more type constraints to be enforced at compile time:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;IntLit&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Pair&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;App&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Abs&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;
	 
	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;rec&lt;/span&gt; &lt;span class='n'&gt;eval&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;IntLit&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='c'&gt;(* s = int here *)&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Pair&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;y&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;eval&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;eval&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='c'&gt;(* s = &amp;#39;a * &amp;#39;b here *)&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;App&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;eval&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;eval&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
	  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Abs&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this example of a typed interpreter, the &lt;code&gt;eval&lt;/code&gt; function is annotated with a &lt;code&gt;type s . s t -&amp;gt; s&lt;/code&gt; type that lets each branch of the pattern match have a constrained type for &lt;code&gt;s&lt;/code&gt; depending on the use. This reminded me of Edwin Brady&amp;#8217;s &lt;a href='http://www.cs.st-andrews.ac.uk/~eb/writings/icfp10.pdf'&gt;partial evaluation&lt;/a&gt; work using dependent types, but a much more restricted version suitable for OCaml.&lt;/p&gt;

&lt;p&gt;There are some really interesting uses for GADTs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforcing invariants in data structures, as with the typed interpreter example above.&lt;/li&gt;

&lt;li&gt;Reflecting types into values means that libraries such as our own &lt;a href='http://github.com/mirage/dyntype'&gt;dyntype&lt;/a&gt; can be expressed in the core language without lots of camlp4 hacks. Finally, this should make typed I/O generators for XML, JSON and other network formats much simpler.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The challenges in the implementation are that principle type inference is now impossible (so some annotation is required), and pattern matching warnings are also trickier.&lt;/p&gt;

&lt;p&gt;From the IDE perspective, the third bit of work is to have the OCaml compiler save the full abstract syntax tree annotation with source locations, scoping information, types (declared and inferred) and addition user-defined annotations. This generalises the &lt;code&gt;-annot&lt;/code&gt; flag and can help projects like &lt;a href='http://jun.furuse.info/hacks/ocamlspotter'&gt;OCamlSpotter&lt;/a&gt;, &lt;a href='http://ocamlwizard.lri.fr/'&gt;OCamlWizard&lt;/a&gt;, &lt;a href='http://www.algo-prog.info/ocaide/'&gt;OcaIDE&lt;/a&gt;, etc. It also helps code-generators driven by type-generators (such as our &lt;a href='http://github.com/mirage/orm'&gt;SQL ORM&lt;/a&gt; or &lt;a href='http://oss.wink.com/atdgen/'&gt;ATDgen&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The OCaml consortium has new members; &lt;a href='http://mlstate.com'&gt;MLState&lt;/a&gt; and &lt;a href='http://mylife.com'&gt;MyLife&lt;/a&gt;, and &lt;a href='http://www.esterel-technologies.com/'&gt;Esterel&lt;/a&gt;, &lt;a href='http://www.ocamlpro.com'&gt;OCamlPro&lt;/a&gt; and one unnamed new member are joining. The consortium goals are to sell permissive licensing (BSD) to members, and sound off new features with the serious users. Three companies are now doing commercial development (Gerd, OCamlCore, OCamlPro) which is growing the community nicely.&lt;/p&gt;

&lt;h3 id='jocaml'&gt;JoCaml&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://pauillac.inria.fr/~maranget/'&gt;Luc Maranget&lt;/a&gt; (who looks like an archetypal mad professor!) gave a great rundown on &lt;a href='http://jocaml.inria.fr/'&gt;JoCaml&lt;/a&gt;, a distributed programming extension to OCaml. This extends the compiler with join-definitions (a compiler patch), and a small bit of runtime support (using Thread), and significant extensions for concurrent and distributed programming in a type-safe way.&lt;/p&gt;

&lt;p&gt;It extends the syntax with three new keywords: &lt;code&gt;def&lt;/code&gt;, &lt;code&gt;spawn&lt;/code&gt; and &lt;code&gt;reply&lt;/code&gt;, and new usage for &lt;code&gt;or&lt;/code&gt; and &lt;code&gt;&amp;amp;&lt;/code&gt; (you should be using &lt;code&gt;||&lt;/code&gt; and &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; anyway). Binary libraries remain compatible between matching versions of JoCaml and OCaml. An example of JoCaml code is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;create&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
	  &lt;span class='n'&gt;def&lt;/span&gt; &lt;span class='n'&gt;st&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;rem&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;tick&lt;/span&gt;&lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;st&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;rem&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
	  &lt;span class='ow'&gt;or&lt;/span&gt; &lt;span class='n'&gt;st&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;wait&lt;/span&gt;&lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;reply&lt;/span&gt; &lt;span class='k'&gt;to&lt;/span&gt; &lt;span class='n'&gt;wait&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
	  &lt;span class='n'&gt;spawn&lt;/span&gt; &lt;span class='n'&gt;st&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;tick&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='n'&gt;tick&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;wait&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='n'&gt;wait&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt;
	
	&lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
	  &lt;span class='n'&gt;tick&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='nn'&gt;Join&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chan&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
	  &lt;span class='n'&gt;wait&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
	&lt;span class='o'&gt;}&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After &lt;code&gt;n&lt;/code&gt; messages to &lt;code&gt;tick&lt;/code&gt;, the &lt;code&gt;wait&lt;/code&gt; barrier function will be called.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;create&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;
	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
	  &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;to&lt;/span&gt; &lt;span class='mi'&gt;9&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
	   &lt;span class='n'&gt;spawn&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; &lt;span class='n'&gt;printf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;%i&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;tick&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt;
	  &lt;span class='k'&gt;done&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
  	  &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;wait&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here we asynchronously print the numbers of &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;9&lt;/code&gt;, and then the &lt;code&gt;wait&lt;/code&gt; call acts as a barrier until it finishes. JoCaml is useful for distributed fork-join parallelism tasks such as raytracing, but with the type system support of OCaml. It is a bit like MapReduce, but without the data partitioning support of Hadoop (and is more light-weight). It would be quite interesting to combine some of the JoCaml extensions with the dynamic dataflow graphs in our own &lt;a href='http://www.cl.cam.ac.uk/research/srg/netos/ciel/'&gt;CIEL&lt;/a&gt; distributed execution engine.&lt;/p&gt;

&lt;h3 id='forgetful_memoisation_in_ocaml'&gt;Forgetful Memoisation in OCaml&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://www.lri.fr/~bobot/'&gt;Francois Bobot&lt;/a&gt; talks about the problem of memoizing values so that they can be re-used (e.g. in a cache). Consider a standard memoiser:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;memo_f&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;
	  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;cache&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;create&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
	  &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	    &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt; &lt;span class='n'&gt;cache&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;
	    &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;
	      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt;
	      &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;cache&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
	      &lt;span class='n'&gt;v&lt;/span&gt;
	
	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;v1&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;memo_f&lt;/span&gt; &lt;span class='n'&gt;k1&lt;/span&gt;
	&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;v2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;memo_f&lt;/span&gt; &lt;span class='n'&gt;k2&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='c'&gt;(* k2 = k1 in O(1) *)&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If a key is not reachable from anywhere other than the heap, we want to eliminate it from the cache also. The first solution is a normal hashtable, but this results in an obvious memory leak since a key held in the cache marks it as reachable. A better solution is using OCaml &lt;a href='http://caml.inria.fr/pub/docs/manual-ocaml/libref/Weak.html'&gt;weak pointers&lt;/a&gt; that permit references to values without holding on to them (see &lt;a href='http://www.pps.jussieu.fr/~li/software/weaktbl/doc/html/Weaktbl.html'&gt;Weaktbl&lt;/a&gt; by &lt;a href='http://www.pps.jussieu.fr/~li/'&gt;Zheng Li&lt;/a&gt; who is now an OCaml hacker at Citrix). The problem with Weaktbl is that if the value points to the key, forming a cycle which will never be reclaimed.&lt;/p&gt;

&lt;p&gt;Francois solves this by using &lt;a href='http://en.wikipedia.org/wiki/Ephemeron'&gt;Ephemerons&lt;/a&gt; from Smalltalk. They use the rule that the value can be reclaimed if the key or the ephemeron itself can be reclaimed by the GC, and have a signature like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;	&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Ephemeron&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;sig&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;create&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;check&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;bool&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='n'&gt;option&lt;/span&gt;
	  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;get_key&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;option&lt;/span&gt;
	&lt;span class='k'&gt;end&lt;/span&gt;
	
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The implementation in OCaml patches the runtime to use a new tag for ephemerons, and the performance graphs in his &lt;a href='https://forge.ocamlcore.org/docman/view.php/77/134/memoization2011.pdf'&gt;slides&lt;/a&gt; look good. This is an interesting topic for me since we need efficient memoisation in Mirage I/O (see the effects on DNS performance in the &lt;a href='http://anil.recoil.org/papers/2007-eurosys-melange.pdf'&gt;Eurosys paper&lt;/a&gt; which used Weaktbl). When asked if the OCaml patch will be upstreamed, &lt;a href='http://gallium.inria.fr/~doligez/'&gt;Damien Doligez&lt;/a&gt; did not like the worst-case complexity of long chains of ephemerons in the GC, and there are several approaches under consideration to alleviate this without too many changes to the runtime, but Francois believes the current complexity is not too bad in practise.&lt;/p&gt;

&lt;h3 id='oasis_and_website'&gt;Oasis and website&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://sylvain.le-gall.net/'&gt;Sylvain&lt;/a&gt; came on stage later to give a demonstration of &lt;a href='http://oasis.forge.ocamlcore.org/oasis-db.html'&gt;OASIS&lt;/a&gt;, an equivalent of &lt;a href='http://www.haskell.org/cabal/'&gt;Cabal&lt;/a&gt; for Haskell or &lt;a href='http://www.cpan.org/'&gt;CPAN&lt;/a&gt; for Perl. It works with a small &lt;code&gt;_oasis&lt;/code&gt; file that describes the project, and then the OASIS tool auto-generates &lt;code&gt;ocamlbuild&lt;/code&gt; files from it (this reminds me of Perl&amp;#8217;s &lt;a href='http://perldoc.perl.org/ExtUtils/MakeMaker.html'&gt;MakeMaker&lt;/a&gt;). Once the files are auto-generated, it is self-contained and there is no further dependency on OASIS itself.&lt;/p&gt;

&lt;p&gt;OASIS works with either an existing build system in a project, or can be integrated more closely with &lt;code&gt;ocamlbuild&lt;/code&gt; by advanced users. Lots of projects are already using OASIS (from Cryptokit to Lwt to the huge &lt;a href='http://caml.inria.fr/cgi-bin/hump.en.cgi?contrib=641'&gt;Jane Street Core&lt;/a&gt;). He is also working on a distribution mechanism on a central website, which should make for convenient OCaml packaging when it is finished and gets more adoption from the community.&lt;/p&gt;

&lt;p&gt;Finally, &lt;a href='http://ashishagarwal.org/'&gt;Ashish Agarwal&lt;/a&gt; led a discussion on how OCaml can improve its web presence for beginners. Lots of good ideas here (some of which we implemented when reworking the &lt;a href='http://cufp.org'&gt;CUFP&lt;/a&gt; website last year). Looking forward to seeing what happens next year in this space! I really enjoyed the day; the quality of talks was very high, and many engaging discussions from all involved!&lt;/p&gt;
&lt;table width='90%' align='center'&gt;
&lt;tr&gt;
&lt;td width='30%' class='bimg'&gt;&lt;a href='http://anil.recoil.org/images/ocaml-users-1.jpg'&gt;&lt;img width='120' border='0' src='http://anil.recoil.org/images/ocaml-users-1-thumb.jpg' /&gt;&lt;/a&gt;&lt;br /&gt;How many OCaml hackers does it take to change a lightbulb?&lt;/td&gt;
&lt;td width='30%' class='bimg'&gt;&lt;a href='http://anil.recoil.org/images/ocaml-users-3.jpg'&gt;&lt;img width='120' border='0' src='http://anil.recoil.org/images/ocaml-users-3-thumb.jpg' /&gt;&lt;/a&gt;&lt;br /&gt;Wearing bibs at French Teppinyaki&lt;/td&gt;
&lt;td width='30%' class='bimg'&gt;&lt;a href='http://anil.recoil.org/images/ocaml-users-2.jpg'&gt;&lt;img width='120' border='0' src='http://anil.recoil.org/images/ocaml-users-2-thumb.jpg' /&gt;&lt;/a&gt;&lt;br /&gt;Team Mirage cheeses it up&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;a href='http://anil.recoil.org/images/sf-ocaml.jpg'&gt;&lt;img style='float:right' src='http://anil.recoil.org/images/sf-ocaml-thumb.jpg' /&gt;&lt;/a&gt;
&lt;p&gt;Of course, not all of the OCaml community action is in France. The ever-social &lt;a href='http://www.twitter.com/jakedonham'&gt;Jake Donham&lt;/a&gt; organised the First Ever San Francisco User Group that I attended when I was over there a few weeks ago. Ok, admittedly it was mainly French people there too, but it was excellent to meet up with &lt;a href='http://www.linkedin.com/pub/mika-illouz/1/a02/7b4'&gt;Mika&lt;/a&gt;, &lt;a href='http://martin.jambon.free.fr/'&gt;Martin&lt;/a&gt;, &lt;a href='http://www.linkedin.com/pub/julien-verlaguet/20/10a/b57'&gt;Julien&lt;/a&gt;, &lt;a href='http://fr.linkedin.com/in/henribinsztok'&gt;Henri&lt;/a&gt; and of course Jake when over there.&lt;/p&gt;

&lt;p&gt;We should definitely have more of these fun local meetups, and a number of other OCaml hackers I mentioned it to want to attend next time in the Bay Area, if only to cry into their drinks about the state of multi-core&amp;#8230; &lt;em&gt;just kidding&lt;/em&gt;, &lt;a href='http://www.ocamlpro.com'&gt;OCamlPro&lt;/a&gt; is hard at work fixing that after all :-)&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Commercial Users of Functional Programming (CUFP) 2011</title>
   <link href="http://anil.recoil.org/2011/04/13/cufp2011.html"/>
   <updated>2011-04-13T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2011/04/13/cufp2011</id>
   <content type="html">&lt;p&gt;&lt;a href='http://cufp.org/users/yminsky'&gt;Yaron Minsky&lt;/a&gt; and I are co-chairing the &lt;a href='http://cufp.org'&gt;Commercial Users of Functional Programming&lt;/a&gt; workshop this year. It&amp;#8217;s going to be held in Tokyo in September alongside &lt;a href='http://www.icfpconference.org/'&gt;ICFP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The event is definitely the highlight of my conference calendar: a very diverse set of academics, industrial types and web hackers all mingle and argue till the early hours. There is also an expanded tutorial series (where &lt;a href='http://dave.recoil.org'&gt;David Scott&lt;/a&gt; and I plan to hold a session on constructing &lt;a href='http://www.openmirage.org/'&gt;functional operating systems&lt;/a&gt;!), as well as BoF sessions for nailing down ideas with a smaller group of people.&lt;/p&gt;

&lt;p&gt;The deadline for presentation proposals is June 15th (just a short abstract and bio required), so head over to the &lt;em&gt;&lt;a href='http://cufp.org/2011-call-presentations'&gt;Call for Proposals&lt;/a&gt;&lt;/em&gt; and get writing!&lt;/p&gt;

&lt;p&gt;If you are curious about past events, check out the &lt;a href='http://cufp.org/videos'&gt;videos&lt;/a&gt; from previous years. Two of my personal favourite talks are Eugene Letuchy talking about &lt;a href='http://player.vimeo.com/video/6699769'&gt;how they used Erlang at Facebook&lt;/a&gt; to build the popular chat functionality, and &lt;a href='http://monkey.org/~marius'&gt;Marius Eriksen&lt;/a&gt; describing Scala for the geo-database at Twitter (embedded below).&lt;/p&gt;
&lt;iframe width='400' frameborder='0' src='http://player.vimeo.com/video/16753839' height='300'&gt; &amp;nbsp;&lt;/iframe&gt;</content>
 </entry>
 
 <entry>
   <title>Yurts for Digital Nomads</title>
   <link href="http://anil.recoil.org/2010/04/29/yurts-for-digital-nomads.html"/>
   <updated>2010-04-29T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2010/04/29/yurts-for-digital-nomads</id>
   <content type="html">&lt;p&gt;The App Engine data collector for Personal Containers is coming on nicely, and is on track for an alpha preview release &lt;a href='http://github.com/avsm/perscon/blob/master/README.md'&gt;fairly soon&lt;/a&gt;. Working with AppEngine has been interesting; it&amp;#8217;s got excellent availability and you can&amp;#8217;t beat the price (free), but coding robust Python that doesn&amp;#8217;t trip over the tight resource limits for individual requests, asynchronous tasks and queries is tricky. While it is good for small records such as my &lt;a href='http://github.com/avsm/perscon/tree/master/plugins/iPhone/'&gt;iPhone&lt;/a&gt; or Find My iPhone &lt;a href='http://github.com/avsm/perscon/blob/master/appengine/perscon/drivers/fmi.py'&gt;GPS traces&lt;/a&gt; traces, it doesn&amp;#8217;t work so well with my gigabytes of photographs or decades of e-mail.&lt;/p&gt;

&lt;p&gt;This confirmed our earlier intuition that there is no one perfect solution for personal data handling; instead, we need to &lt;em&gt;embrace diversity&lt;/em&gt; and construct an infrastructure that can cope with change over the coming decades. Mobile programming has changed beyond recognition in just a few years, and cloud providers are specialising in different ways (e.g. &lt;a href='http://www.picloud.com/'&gt;PiCloud&lt;/a&gt; for simple compute, or &lt;a href='http://aws.amazon.com'&gt;EC2&lt;/a&gt; for fancy services like elastic &lt;a href='http://aws.amazon.com/elasticloadbalancing/'&gt;load balancing&lt;/a&gt;).&lt;/p&gt;
&lt;a href='http://anil.recoil.org/images/nomads-diagram.png'&gt;&lt;img style='float:right' src='http://anil.recoil.org/images/nomads-diagram-300.png' /&gt;&lt;/a&gt;
&lt;p&gt;So to recognise this, we are building components that all interoperate with your personal data, keep it secure, and ensure it persists for more than a few years. &lt;a href='http://www.malteschwarzkopf.de/'&gt;Malte Schwarzkopf&lt;/a&gt; came up with the term &amp;#8220;digital &lt;a href='http://en.wikipedia.org/wiki/Yurt'&gt;yurts&lt;/a&gt;&amp;#8221;, and it&amp;#8217;s stuck. We&amp;#8217;ve written a &lt;a href='http://perscon.net/papers/digital-yurts-draft1.pdf'&gt;draft paper&lt;/a&gt; about it, and would love to hear your comments and feedback on the approach.&lt;/p&gt;

&lt;p&gt;There are some interesting recent trends that make doing this particularly important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The New York Times wrote about the &lt;a href='http://www.nytimes.com/2010/05/02/magazine/02self-measurement-t.html'&gt;data-driven life&lt;/a&gt; increasingly influencing our decision making. Current sensor data such as GPS traces are just harbringers for the privacy disaster that would be information such as heart rates or your consumption habits getting into the public domain. &lt;em&gt;(link via &lt;a href='http://www.cl.cam.ac.uk/~dgm36/'&gt;Derek Murray&lt;/a&gt;)&lt;/em&gt;.&lt;/li&gt;

&lt;li&gt;Facebook has announced a brand new API platform to get access to your information. The &lt;a href='http://eff.org'&gt;EFF&lt;/a&gt; has a fantastic timeline of &lt;a href='http://www.eff.org/deeplinks/2010/04/facebook-timeline'&gt;Facebook&amp;#8217;s Eroding Privacy&lt;/a&gt; over the last five years, to demonstrate how unsafe it is to trust your data to any third-party. We&amp;#8217;ve started developing an information dump plugin for Facebook, but the API just changed mid-way and so it has to be started again (volunteers welcome!).&lt;/li&gt;

&lt;li&gt;In the UK, the &lt;a href='http://en.wikipedia.org/wiki/Digital_Economy_Act_2010'&gt;Digital Economy Act&lt;/a&gt; is an extremely controversial act that makes anonymity and privacy all the more important. We&amp;#8217;re assembling an open-source &lt;a href='http://www.scribd.com/doc/28393106/Using-Dust-Clouds-to-Enhance-Anonymous-Communication'&gt;dust cloud&lt;/a&gt; that integrates Tor into personal containers to automatically grant you anonymity as you communicate with your friends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you&amp;#8217;re interested, join our &lt;a href='http://perscon.net/contact.html'&gt;group&lt;/a&gt; or contact &lt;a href='http://anil.recoil.org'&gt;me&lt;/a&gt; directly. At this stage, you need desire and the ability to hack code, but things are settling down over the next few months&amp;#8230;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Pulling together a user interface</title>
   <link href="http://anil.recoil.org/2010/04/15/uiprototype.html"/>
   <updated>2010-04-15T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2010/04/15/uiprototype</id>
   <content type="html">&lt;p&gt;We&amp;#8217;ve been &lt;a href='http://github.com/avsm/perscon'&gt;hacking&lt;/a&gt; away on fleshing out the &lt;a href='http://code.google.com/appengine'&gt;App Engine&lt;/a&gt; node for personal containers. We&amp;#8217;re building this node first because, crucially, deploying an App Engine VM is free to anyone with a Google account. &lt;a href='http://anil.recoil.org/images/perscon-extjs.png'&gt;&lt;img style='float:right' src='http://anil.recoil.org/images/perscon-extjs-thumb.png' /&gt;&lt;/a&gt; The service itself is limited since you can only respond to HTTP or XMPP requests and do HTTP fetches, and so its primary use is as an always-on data collection service with a webmail-style UI written using &lt;a href='http://www.extjs.com/'&gt;extjs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Personal containers gather data from a wide variety of sources, and normalise them into a format which understands people (address book entries, with a set of services such as e-mail, phone, IM and online IDs), places (GPS, WOEID), media (photos, movies) and messages (Tweets, emails, Facebook messages). I&amp;#8217;ll post more about the data model behind personal containers in a follow-up as the format settles.&lt;/p&gt;

&lt;p&gt;The App Engine node has a number of plugins to gather data and aggregate them into a single view (see screenshot). Plugins include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/iPhoto/'&gt;iPhoto&lt;/a&gt; &lt;img width='15' src='http://anil.recoil.org/images/iphoto_30x30.png' /&gt; extracts location (via EXIF), people present (associated via &lt;a href='http://gizmodo.com/5141741/what-to-know-about-iphoto-09-face-detection-and-recognition'&gt;faces&lt;/a&gt;), and of course, the actual photograph.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/Adium/'&gt;Adium&lt;/a&gt; &lt;img width='15' src='http://anil.recoil.org/images/chat_30x30.png' /&gt; logs all IMs into a threaded chat view.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/iPhone/'&gt;iPhone&lt;/a&gt; &lt;img width='15' src='http://anil.recoil.org/images/phone_30x30.png' /&gt; uses the backup files on a Mac to extract SMS messages, phone call records (and it could also get photographs and browsing history, although it currently doesn&amp;#8217;t). An AppEngine tracker can also use &lt;a href='http://www.apple.com/mobileme/features/find-my-iphone.html'&gt;FindMyIPhone&lt;/a&gt; to poll your iPhone regularly to keep track of your location without publishing it to Google or Yahoo (and hopefully in iPhone 4.0, we can operate as a background service at last!).&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/appengine/twitter.py'&gt;Twitter&lt;/a&gt; &lt;img width='15' src='http://anil.recoil.org/images/twitter_30x30.png' /&gt; runs directly on AppEngine (authenticated via OAuth) and synchronizes with a Twitter feed.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/avsm/perscon/tree/master/plugins/MacOS-SyncServices/'&gt;SyncServices&lt;/a&gt; hooks into the MacOS X &lt;a href='http://developer.apple.com/macosx/syncservices.html'&gt;sync framework&lt;/a&gt; and initially subscribes to Address Book updates. This seems to be the first open-source sync alternative to the expensive Mobile Me, as far as I can tell. I&amp;#8217;m planning to expand this to also subscribe to the full set of sync information (e.g. calendars).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;m switching tacks briefly; we received an &lt;a href='http://aws.amazon.com/education/aws-in-education-research-grants/'&gt;Amazon Research Grant&lt;/a&gt; recently and I&amp;#8217;m building a node that runs as a Linux server to act as a longer-term archival and search server. This is being written in OCaml and uses &lt;a href='http://1978th.net/tokyocabinet/'&gt;Tokyo Cabinet&lt;/a&gt; (with Jake Donham&amp;#8217;s excellent &lt;a href='http://github.com/jaked/otoky'&gt;bindings&lt;/a&gt;) and so should be speedy and a useful alternative implementation of the HTTP REST interface. The plan is to automatically synchronize meta-data across all the nodes of a personal container, but store large and historical data away from expensive cloud storage such as App Engine.&lt;/p&gt;

&lt;p&gt;There are lots more plugins in development, such as &lt;a href='http://foursquare.com'&gt;Foursquare&lt;/a&gt; and &lt;a href='http://gowalla.com'&gt;Gowalla&lt;/a&gt; OAuth collectors, an &lt;a href='http://github.com/avsm/perscon/tree/master/android'&gt;Android&lt;/a&gt; mobile application to upload location and contacts information, and Google GData synchronization. If you&amp;#8217;re interested in one of these or something else, please do &lt;a href='http://perscon.net/contact.html'&gt;get in touch&lt;/a&gt; or just fork the &lt;a href='http://github.com/avsm/perscon'&gt;project&lt;/a&gt; and start hacking!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Opening a website</title>
   <link href="http://anil.recoil.org/2010/03/29/intro.html"/>
   <updated>2010-03-29T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2010/03/29/intro</id>
   <content type="html">&lt;p&gt;We&amp;#8217;ve been working away at building a new type of database to help individuals keep reigns on their ever-increasing personal digital information. The first prototypes run freely on &lt;a href='http://code.google.com/appengine'&gt;Google App Engine&lt;/a&gt; to gather your data behind-the-scenes, and we are working on more advanced versions that run on embedded devices and the cloud.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re interested in keeping track of your personal data, you can start off with the &lt;a href='http://perscon.net/install.html'&gt;installation&lt;/a&gt; instructions to clone your own version. After that, read up on the &lt;a href='http://perscon.net/design.html'&gt;design&lt;/a&gt; of the system (which is still changing as we research new ideas around it). When you find something you want to fix, or add a new plugin data source, just clone the &lt;a href='http://github.com/avsm/perscon'&gt;code&lt;/a&gt; and send us back fixes!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>C#, F# and Other Programming Language Fun at PDC 2008</title>
   <link href="http://anil.recoil.org/2008/11/01/c-f-and-other-programming-language-fun-at-pdc-2008.html"/>
   <updated>2008-11-01T00:00:00+00:00</updated>
   <id>http://anil.recoil.org/2008/11/01/c-f-and-other-programming-language-fun-at-pdc-2008</id>
   <content type="html">&lt;p&gt;My favourite session of &lt;a href='http://www.microsoftpdc.com/'&gt;PDC 2008&lt;/a&gt; was by &lt;a href='http://en.wikipedia.org/wiki/Anders_Hejlsberg'&gt;Anders Hejlsberg&lt;/a&gt; as he described the &lt;a href='http://channel9.msdn.com/pdc2008/TL16/'&gt;Future of C#&lt;/a&gt;. Anders is an excellent speaker, and it was educational watching how he made fairly complex type systems come across to an audience more used to simpler programming languages. I say this after attending &lt;a href='http://www.icfpconference.org/'&gt;ICFP&lt;/a&gt; recently, where that wasn&amp;#8217;t true of all the presentations!&lt;/p&gt;

&lt;p&gt;The high-level message was exactly what I wanted to hear: in order to exploit multi-core processors more effectively, Microsoft&amp;#8217;s languages are focussing on improvements in three areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Declarative&lt;/em&gt; constructs: making the programmer define overall goals and constraints enables a tool-chain to more effectively scale computation across multiple processors. An example of this in C# 3.0 is the &lt;a href='http://msdn.microsoft.com/en-us/library/bb308959.aspx'&gt;Language Integrated Query&lt;/a&gt; (LINQ) domain specific language for defining queries.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;em&gt;Dynamic&lt;/em&gt; interoperability: Although Anders is a big fan of static type systems (robust, high-performance, enable intelligent tools), he pointed out that a lot of the systems that C# programmers have to deal with are fundamentally dynamic. Examples are web interfaces such as SOAP/REST APIs, COM objects for talking to other Microsoft applications, or scripting language integration (e.g. Python or Ruby).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;em&gt;Concurrent&lt;/em&gt; programming: dealing with multiple cores requires splitting up computation into parallel threads, and the resulting parallel mass of code is often hard to debug (e.g. difficulties of reproducing obscure concurrency issues) and statically reason about.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An interesting aside was his assertion about &amp;#8220;co-evolution&amp;#8221;. Microsoft have a number of languages which have recently been unified under the CLR, such as Visual Basic, C# and most recently &lt;a href='http://research.microsoft.com/fsharp/'&gt;F#&lt;/a&gt;. Rather than have one language race ahead of the others, they like to &amp;#8220;borrow&amp;#8221; features as appropriate into other languages. This is obviously made easier by having a common run-time foundation, and an example of co-evolution is the introduction of &lt;a href='http://blogs.msdn.com/ericwhite/pages/Lambda-Expressions.aspx'&gt;lambdas&lt;/a&gt; into C# 3.0 as obviously seen in F#.&lt;/p&gt;

&lt;h2 id='concurrency'&gt;Concurrency&lt;/h2&gt;

&lt;p&gt;Anders observes that all the attempts to automatically parallelize software has not yielded good results in the past, and so support needs to be built into the language to do &amp;#8220;top-down&amp;#8221; parallelism instead of the compiler inferring it from the bottom-up. To this end, they are introducing &lt;a href='http://blogs.msdn.com/somasegar/archive/2007/11/29/parallel-extensions-to-the-net-fx-ctp.aspx'&gt;parallel extensions&lt;/a&gt; into the .NET framework. This makes use of functional features to parallelize code, including LINQ queries or CPU-intensive compute.&lt;/p&gt;

&lt;p&gt;For an example of how this code looks, check out Jurgen Van Gael&amp;#8217;s post on using &lt;a href='http://undirectedgrad.blogspot.com/2007/12/f-and-task-parallel-library.html'&gt;F# with the Task Parallel Library&lt;/a&gt;. I wanted to learn more about this, and wandered over to the Hands On Labs where F# and Visual Studio 10 were all pre-installed. I then ran into an extremely cool feature of F#&amp;#8230; &lt;a href='http://blogs.msdn.com/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx'&gt;asynchronous workflows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;F# introduces an extension to the usual &lt;code&gt;let&lt;/code&gt; ML operator in the form of &lt;code&gt;let!&lt;/code&gt;. As &lt;a href='http://blogs.msdn.com/dsyme/'&gt;Don Syme&lt;/a&gt; explains on his &lt;a href='http://blogs.msdn.com/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx'&gt;blog&lt;/a&gt; ), this can be interpreted as &lt;em&gt;&amp;#8220;run the asynchronous computation on the right and wait for its result. If necessary suspend the rest of the workflow as a callback awaiting some system event&amp;#8221;&lt;/em&gt;. So this construct lets you write straight-line code which can potentially block, without the hassle of spawning threads or encoding continuation passing style constructs in the code. Already a nice improvement over OCaml! (although to be fair I&amp;#8217;ve not had a chance to check out some of the &lt;a href='http://camlp3l.inria.fr/eng.htm'&gt;parallel OCaml extensions&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id='dynamic_programming'&gt;Dynamic Programming&lt;/h2&gt;

&lt;p&gt;Dynamic programming is the main focus of C# 4.0. In order to support dynamic objects as first-class citizens in a statically typed world, they introduce a &lt;code&gt;dynamic&lt;/code&gt; static type. This forces all method resolution on that object to happen at run-time and disables static checks by the compiler (aside from looking from mixups between dynamic and static objects). The &lt;code&gt;dynamic&lt;/code&gt; type now makes it easy to wrap support for Python, Ruby and Javascript, since the relevant dispatch functions can all be hidden away in the method resolver at run-time, leaving the programmer with a single syntax for invoking methods across these different languages.&lt;/p&gt;

&lt;p&gt;The actual definition of method resolvers is pretty straight-forward; he demonstrated custom getters and setters (similar to Python for example) by using the &lt;code&gt;IDynamicObject&lt;/code&gt; interface to define actions to take when properties are accessed. His example did the usual dictionary wrapper which mapped setting arbitrary properties onto an internal dictionary variable.&lt;/p&gt;

&lt;p&gt;Another improvement in this space is the addition of optional arguments and labelled arguments. Both of these have well-defined semantics (optional arguments have to come after non-optional ones, and evaluation of arguments is left-to-right) and are purely syntactic improvements with no run-time cost. One of the best examples he showed of using these around COM interoperability. In current versions of C#, due to the lack of named arguments a common function such as &lt;em&gt;&amp;#8220;Save As&amp;#8221;&lt;/em&gt; might require 12 or more stub arguments to be specified as &lt;code&gt;ref missing&lt;/code&gt;. Now, those long, repetitive lines can be folded down to only the arguments which are required.&lt;/p&gt;

&lt;p&gt;Sort of related to the earlier co-evolution was his demonstration of how similar Javascript and C# syntax is now with this new support. He took a Silverlight 2 code snippet written in Javascript and ported it over to C# 4.0 with some very mechanical changes. The languages are definitely converging fast!&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re interested in checking out more on this topic, look at &lt;a href='http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython'&gt;IronPython&lt;/a&gt;, the &lt;a href='http://en.wikipedia.org/wiki/Dynamic_Language_Runtime'&gt;Dynamic Language Runtime&lt;/a&gt; (DLR), and the &lt;a href='http://channel9.msdn.com/pdc2008/TL10/'&gt;TL10&lt;/a&gt; session on dynamic languages on .NET. The DLR is currently maintained as part of IronPython, but is being moved out to sit on top of the CLR for more languages such as Visual Basic, Javascript or COM. The DLR covers common optimizations which are useful for scripting languages, such as call-site caching, dynamic dispatch and expression trees (e.g. for LINQ). The DLR has a bunch of binders which bridge between different backends such as .NET, Silverlight, the native Python or Ruby backends, or COM applications such as Microsoft office.&lt;/p&gt;

&lt;h2 id='metaprogramming'&gt;Meta-programming&lt;/h2&gt;

&lt;p&gt;Later on at the &lt;a href='http://channel9.msdn.com/pdc2008/TL57/'&gt;Future of Programming Languages&lt;/a&gt; panel session, Anders talked about meta-programming as being one of the future improvement he&amp;#8217;s looking at. Currently, there is a lot of ad-hoc code generation in place when creating Windows applications, and unifying this into the language would give safety and maintainability improvements.&lt;/p&gt;

&lt;p&gt;In order to do this, for C# 5.0 they are rewriting the compiler to be self-hosting in C#, since it has historically been a C++ application. This permits them to switch the compiler from being a traditional &amp;#8220;black box&amp;#8221; compiler to a hosted .NET service which can be called directly by .NET programs in order to do dynamic run-time compilation of code. Other portions of the compiler chain are also exposed to permit incremental program construction by third-party code.&lt;/p&gt;

&lt;p&gt;He demonstrated this with a pretty nifty C# top-level, into which he directly typed Winforms code to construct a window with a few simple buttons using the C# compiler server. Not to be outdone by this, &lt;a href='http://tirania.org/'&gt;Miguel de Icaza&lt;/a&gt; promptly upstaged Anders at his (fantastic) &lt;a href='http://channel9.msdn.com/pdc2008/PC54/'&gt;Mono 2.2 session&lt;/a&gt;. He demonstrated the new C# shell which is present in Mono trunk builds and can essentially be used like an OCaml or Python top-level to mess around and manipulate C# code. He also talked about embedded Mono and SIMD support which pushes their compiler ahead of Microsoft&amp;#8217;s in the 3D performance game.&lt;/p&gt;

&lt;h2 id='summary'&gt;Summary&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;m firmly convinced about the potential of F# now. I had the opportunity at the Open Spaces area to quiz &lt;a href='http://weblogs.asp.net/Scottgu/'&gt;Scott Guthrie&lt;/a&gt; about whether or not F# was a toy language. He replied using the same arguments as Anders that the higher-level language approach (declarative, functional) was very important strategically to Microsoft to let their developer platform continue to survive in a multi-core world.&lt;/p&gt;

&lt;p&gt;This boils down to the individual languages not being that important any more (as seen by the sharing of features between C# and F#), and the underlying execution layer (the CLR/DLR) adding efficient support. Now any old language can adopt higher-level features without having to re-do all the optimization grunt work again and again. Much like &lt;a href='http://www.xen.org'&gt;Xen&lt;/a&gt; offers a new golden age for innovative new OS research by freeing programmers from writing a million hardware device drivers, it looks like .NET is ushering in a new age of programming language innovation!&lt;/p&gt;

&lt;p&gt;Inspired by the PDC talks, I&amp;#8217;ve got &lt;a href='http://monodevelop.com/'&gt;MonoDevelop&lt;/a&gt; and F# up and running on my Macbook Air, and am just playing with &lt;a href='http://gtk-sharp.sourceforge.net/'&gt;GTK#&lt;/a&gt; and &lt;a href='http://www.mono-project.com/CocoaSharp'&gt;CocoaSharp#&lt;/a&gt;. If this works as well as OCaml, then it might finally be time to abandon the old stalwart and move to a new language for my day-to-day stuff!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Working through TED videos on the train</title>
   <link href="http://anil.recoil.org/2008/10/28/working-through-ted-videos-on-the-train.html"/>
   <updated>2008-10-28T00:00:00+00:00</updated>
   <id>http://anil.recoil.org/2008/10/28/working-through-ted-videos-on-the-train</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m over at the &lt;a href='http://www.microsoftpdc.com/'&gt;Microsoft PDC&lt;/a&gt; in Los Angeles this week, and commuting over from Anand&amp;#8217;s place in Camarillo using the &lt;a href='http://www.metrolinktrains.com/'&gt;Metrolink&lt;/a&gt;. The 3 hour commute gives me a great excuse to catch up on my &lt;a href='http://www.ted.com/'&gt;TED&lt;/a&gt; talks on my iPhone.&lt;/p&gt;

&lt;p&gt;The entire set of talks is &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=160892972'&gt;available&lt;/a&gt; online via iTunes, and these really stood out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Jared Diamond on &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?i=43138920&amp;amp;id=160892972'&gt;Why Societies Collapse&lt;/a&gt; : he talks about lots of civilizations which have reached tipping points and have collapsed, often catastrophically. Not a funny or entertaining one, but lots of solid, well-researched facts. Also see his &lt;a href='http://www.amazon.com/Collapse-Societies-Choose-Fail-Succeed/dp/0670033375'&gt;book&lt;/a&gt; which George Dunlap recommended to me but is still in my reading list.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Mih?ly Cs?kszentmih?lyi on &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?i=42793807&amp;amp;id=160892972'&gt;Creativity, fulfillment and flow&lt;/a&gt; : again, a really well-researched talk which categorizes human motivation into a 2D space of challenge vs skill, and the different emotions which are evoked by being in different situations (e.g. apathy requires no challenge and no skill, and anxiety results if you have low skill and a high challenge ahead of you). The &amp;#8220;flow&amp;#8221; he argues for is the ideal pinnacle of where we should aim to get to in our lives.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Finally, what I consider to be the greatest TED talk I&amp;#8217;ve ever seen is by the late &lt;a href='http://en.wikipedia.org/wiki/Paul_MacCready'&gt;Paul MacCready&lt;/a&gt; on &lt;a href='http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?i=42696989&amp;amp;id=160892972'&gt;Nature vs Humans, and what we can do about it&lt;/a&gt; : he starts off slowly by showing some graphs about the impact of humanity on the population of the planet (hint: we&amp;#8217;ve taken over), and finishes off with some truly awesome demonstrations of natural planes, such as Ornithopters or solar-powered tiny fliers that do not require gas to fly. Highly recommended if you only watch one TED video at all!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are about 80 videos left on my viewing list.. this is going to take a while!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Peeking under the hood of High Availability</title>
   <link href="http://anil.recoil.org/2008/09/17/peeking-under-the-hood-of-high-availability.html"/>
   <updated>2008-09-17T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2008/09/17/peeking-under-the-hood-of-high-availability</id>
   <content type="html">&lt;p&gt;Well, the big launch of &lt;a href='http://www.xenserver5.com/'&gt;XenServer 5&lt;/a&gt; has gone smoothly, and with it have arrived a flood of questions about how exactly the new &lt;a href='http://xenserver5.com/ha.php'&gt;High Availability&lt;/a&gt; functionality works.&amp;#160; I&amp;#8217;ll use this post to explain the overall architecture of HA in XenServer 5, and also how some of the fault detection and failure planning works.&lt;/p&gt;

&lt;p&gt;Fundamentally, HA is about making sure important VMs are always running on a resource pool. There are two aspects to this: reliably &lt;b&gt;detecting host failure&lt;/b&gt;, and computing a &lt;b&gt;failure plan&lt;/b&gt; to deal with swift recovery.&lt;/p&gt;

&lt;p&gt;Detecting host failure reliably is difficult since you need to remotely distinguish between a host disappearing for a while versus exploding in a ball of flames.&amp;#160; If we mistakenly decide that a master host has broken down and elect a new master in its place, there may be unpredictable results if the original host were to make a comeback&amp;#33;&amp;#160;&amp;#160; Similarly, if there is a network issue and a resource pool splits into two equal halves, we need to ensure that only one half accesses the shared storage and not both simultaneously.&lt;/p&gt;

&lt;h2 id='heartbeating_for_availability'&gt;Heartbeating for availability&lt;/h2&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-3b.png'&gt;&lt;img align='right' src='http://anil.recoil.org/images/citrix/ha-wizard-3b-thumb.jpg' /&gt;&lt;/a&gt;
&lt;p&gt;We solve all these problems in XenServer by having two mechanisms: a &lt;b&gt;storage heartbeat&lt;/b&gt; and a &lt;b&gt;network heartbeat&lt;/b&gt;. When you enable HA in a pool, you must nominate an iSCSI or FC storage repository to be the heartbeat SR. XenServer automatically creates a couple of small virtual disks in this SR. The first disk is used by every physical host in the resource pool as a &lt;b&gt;shared quorum disk&lt;/b&gt;. Each host allocates itself a unique block in the shared disk and regularly writes to the block to indicate that it is alive.&lt;/p&gt;

&lt;p&gt;I asked &lt;a href='http://dave.recoil.org/'&gt;Dave 'highly available' Scott&lt;/a&gt;, the principal engineer behind HA about the startup process:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;When HA starts up, all hosts exchange data over both network and storage channels, indicating which hosts &lt;em&gt;they&lt;/em&gt; can see over both channels; i.e. which I/O paths are working and which are not.&amp;#160; This liveness information is exchanged until a fixed point is reached and all of the hosts are satisfied that they are in agreement about what they can see.&amp;#160; When this happens, the HA functionality is &amp;#8216;armed&amp;#8217; and the pool is protected.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;This HA arming process can take a few minutes to settle for larger pools, but is only required when HA is first enabled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;Once HA is active, each host regularly writes storage updates to the heartbeat virtual disk, and network packets over the management interface.&amp;#160; It is vital to ensure that network adapters are &lt;a href='http://docs.xensource.com/XenServer/5.0.0/1.0/en_gb/reference.html#networking-standalone_host_config-bonds'&gt;bonded&lt;/a&gt; for resilience, and that storage interfaces are using &lt;a href='http://docs.xensource.com/XenServer/5.0.0/1.0/en_gb/reference.html#id2557754'&gt;dynamic multipathing&lt;/a&gt; where supported.&amp;#160; This will ensure that any single adapter or wiring failures do not result in any availability issues.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-5.png'&gt;&lt;img align='right' src='http://anil.recoil.org/images/citrix/ha-wizard-5-thumb.jpg' /&gt;&lt;/a&gt;
&lt;p&gt;The worst-case scenario for HA is the situation where a host is thought to be off-line but is actually still writing to the shared storage, since this can result in corruption of persistent data.&amp;#160; In order to prevent this situation without requiring active power strip control, we implemented &lt;b&gt;hypervisor-level fencing&lt;/b&gt;.&amp;#160; This is a Xen modification which will hard-power the host off at a very low-level if it doesn&amp;#8217;t hear regularly from a watchdog process running in the control domain.&amp;#160; Since it is implemented at a very low-level, this also covers the case where the control domain becomes unresponsive for any reason.&lt;/p&gt;

&lt;p&gt;Hosts will self-fence (i.e. power off and restart) in the event of any heartbeat failure unless any of the following hold true:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The storage heartbeat is present for all hosts but the network has partitioned (so that there are now two groups of hosts).&amp;#160; In this case, all of the hosts which are members of the largest network partition stay running, and the hosts in the smaller network partition self-fence.&amp;#160; The assumption here is that the network outage has isolated the VMs, and they ought to be restarted on a host with working networking.&amp;#160; If the network partitions are exactly the same size, then only one of them will self-fence according to a stable selection function.&lt;/li&gt;

&lt;li&gt;If the storage heartbeat goes away but the network heartbeat remains, then the hosts check to see if they can see all other hosts over the network.&amp;#160; If this condition holds true, then the hosts remain running on the assumption that the storage heartbeat server has gone away.&amp;#160; This doesn&amp;#8217;t compromise VM safety, but any network glitches will result in fencing since that would mean both heartbeats have disappeared.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='planning_for_failure'&gt;Planning for failure&lt;/h2&gt;

&lt;p&gt;The heartbeat system gives us reliable notification of host failure, and so we move onto the second step of HA: capacity planning for failure.&lt;/p&gt;

&lt;p&gt;A resource pool consists of several physical hosts (say, 16), each with potentially different amounts of host memory and a different number of running VMs.&amp;#160; In order to ensure that no single host failure will result in the VMs on that host being unrestartable (e.g. due to insufficient memory on any other host), the XenServer pool dynamically computes a &lt;b&gt;failure plan&lt;/b&gt; which calculates the actions that would be taken on any host failure.&lt;/p&gt;

&lt;p&gt;But there&amp;#8217;s one more complexity&amp;#8230; a single host failure plan does not cover more advanced cases such as network partitions which take out entire groups of hosts.&amp;#160; It would be very useful to be able to create a plan that could tolerate more than a single host failure, so that administrators could ignore the first host failure and be safe in the knowledge that (for example) three more hosts could fail before the pool runs out of spare capacity.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s exactly what we do in XenServer&amp;#8230; the resource pool &lt;em&gt;dynamically&lt;/em&gt; computes a failure plan which considers the &amp;#8220;number of host failures to tolerate&amp;#8221; (or &lt;em&gt;nhtol&lt;/em&gt;).&amp;#160; This represents the number of disposable servers in a pool for a given set of protected VMs.&lt;/p&gt;

&lt;p&gt;The planning algorithms are pretty complex, since doing a brute force search of all possible failures across all hosts across all VMs is an exponential problem.&amp;#160; We apply heuristics to ensure we can compute a plan in a reasonably small time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for up to 3 host failures, we do a comprehensive search which tries almost all permutations.&amp;#160; This covers corner cases such as having hosts or VMs with very different amounts of memory (e.g. 4GB vs 128GB).&amp;#160; Rather than calculate memory slots or otherwise approximate results, we just deal with them individually and give very accurate plans.&lt;/li&gt;

&lt;li&gt;for greater than 3 host failures, we make conservative decisions by approximating every VM to be as large as the largest, and considering each host to be the same as the most densely packed host.&amp;#160; We do not approximate the host memory, and so having pools with uneven amounts of host memory will be fine.&amp;#160; However, in approximate planning mode having a single very large VM will result in a low &lt;em&gt;nhtol&lt;/em&gt; value.&amp;#160; If this is a problem, then try to reduce the &lt;em&gt;nhtol&lt;/em&gt; or try to have a more even spread of VM memory sizes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since planning algorithms are designed for unexpected host failures, we only consider absolutely essential resource reservations which would prevent the VM from starting on the alternative host (e.g. storage is visible, and enough memory is present).&amp;#160; We do not perform CPU reservation on the basis that it can be optimised at a later stage via live relocation once the VM is back up and running.&lt;/p&gt;

&lt;h3 id='overcommit_protection'&gt;Overcommit protection&lt;/h3&gt;

&lt;p&gt;We now have HA armed and a failover plan for our VMs.&amp;#160; But what if you want to make changes to your configuration after HA is enabled?&amp;#160; This is dealt with via &lt;b&gt;overcommit protection&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;The XenServer pool dynamically calculates a new failover plan in response to every XenAPI call which would affect it (e.g. starting a new VM).&amp;#160; If a new plan cannot be calculated due to insufficient resources across the pool, the XenServer will return an &lt;b&gt;overcommitment&lt;/b&gt; error message to the client which blocks the operation.&lt;/p&gt;

&lt;h4 id='the_what_if_machine'&gt;The &amp;#8220;What if?&amp;#8221; Machine&lt;/h4&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-4b.png'&gt;&lt;img align='right' src='http://anil.recoil.org/images/citrix/ha-wizard-4b-thumb.jpg' /&gt;&lt;/a&gt;
&lt;p&gt;This overcommit protection would be quite irritating if you have to keep trying things and seeing if a plan exists or not, and so we built in a &amp;#8221;&lt;a href='http://www.gotfuturama.com/Information/Encyc-55-What_If_Machine/'&gt;What If?&lt;/a&gt;&amp;#8221; machine into XenServer to facilitate counter-factual reasoning.&lt;/p&gt;

&lt;p&gt;When reconfiguring HA via XenCenter, you can supply a hypothetical series of VM priorities, and XenServer will return a number of host failures which would be tolerated under this scheme.&amp;#160; This lets you try various combinations of VM protections depending on your business needs, and see if the number of host failures is appropriate to the level of paranoia you desire.&lt;/p&gt;

&lt;p&gt;This can even be done via the CLI, using the snappily named &amp;#8221;&lt;b&gt;xe pool-ha-compute-max-host-failures-to-tolerate&lt;/b&gt;&amp;#8221; when HA is enabled.&lt;/p&gt;

&lt;p&gt;The nice thing about XenServer HA is that it is done at the XenAPI level, and so&amp;#160; any of the standard clients (such as the xe CLI or XenCenter) or any third-party clients which use the XenAPI will all interoperate just fine.&amp;#160; The XenServer pool dynamically recalculates plans in response to the client requests, and so no special &amp;#8220;oracle&amp;#8221; is required outside of the pool to figure out HA plans.&lt;/p&gt;

&lt;p&gt;Finally, HA makes master election completely invisible.&amp;#160; Any host in a pool can be a master host, and the pool database is constantly replicated across all nodes and also backed up to shared storage on the heartbeat SR for additional safety.&amp;#160; Any XenAPI client can connect to any host, and a redirect is issued to the current master host.&lt;/p&gt;

&lt;h2 id='protection_levels'&gt;Protection Levels&lt;/h2&gt;

&lt;p&gt;Each VM in an HA pool can be either &lt;b&gt;fully protected&lt;/b&gt;, &lt;b&gt;best-effort&lt;/b&gt; or &lt;b&gt;unprotected&lt;/b&gt;. VMs which are protected are all included in the failover planning, and if no plan exists for which they can all be reliably restarted then the pool is considered to be overcommitted. Hugh Warrington (who implemented the XenCenter HA support) explained what use protection levels are:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Best-effort VMs are not considered when calculating a failover plan, but the pool will still try to start them as a one-off if a host that is running them fails.&amp;#160; This restart is attempted after all protected VMs are restarted, and if the attempt to start them fails then it will not be retried.&amp;#160; This is a useful setting for test/dev VMs which aren&amp;#8217;t critical to keep running, but would be nice to do so in a pool which also has some important VMs which absolutely must run.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;a href='http://anil.recoil.org/images/citrix/ha-wizard-5.png'&gt;&lt;img align='right' src='http://anil.recoil.org/images/citrix/ha-wizard-5-thumb.jpg' /&gt;&lt;/a&gt;
&lt;p&gt;There are some advanced features which are only available via the CLI.&amp;#160;&amp;#160; Each protected VM in an HA pool can be assigned a numeric &lt;tt&gt;ha-restart-priority&lt;/tt&gt;.&amp;#160; If a pool is well-resourced with a high &lt;em&gt;nhtol&lt;/em&gt;, then these restart priorities are not relevant: the VMs are all guaranteed to be started.&lt;/p&gt;
&lt;p&gt;If more hosts fail than have been planned for, then the priorities are used to determine the order in which VMs are restarted.&amp;nbsp; This ensures that in over-committed pools, the most important VMs are restarted first.&amp;nbsp; Although the pool will start priority 1 VMs first, they might not finish booting before the priority 2 VMs, and so this should not be used as the basis for service ordering.&lt;/p&gt;&lt;p&gt;Note that it's very important to &lt;b&gt;ensure that a VM is agile&lt;/b&gt; when protecting it by HA.&amp;nbsp; If the VM is not agile (e.g has a physical CD drive mapped in from a host), then it can only be assigned Best Effort restart since it is tied to one host.&lt;/p&gt;
&lt;h2 id='xencenter_support_for_ha'&gt;XenCenter support for HA&lt;/h2&gt;
&lt;p&gt;The best practice for HA is not to make configuration changes while it is enabled.&amp;nbsp; Instead, it is intended to be the &quot;2am safeguard&quot; which will restart hosts in the event of a problem when there isn't a human administrator nearby.&amp;nbsp; If you are actively making configuration changes such as applying patches, then HA should be disabled for the duration of these changes.&lt;/p&gt;
&lt;p&gt;XenCenter makes some common changes under HA much more user-friendly, which I asked &lt;a href='http://community.citrix.com/blogs/citrite/ewanm/'&gt;Ewan Mellor&lt;/a&gt; (the principal GUI engineer) about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normally a protected VM cannot be shut down via the CLI or from within the guest (a shutdown from within the guest will automatically restart it).&amp;#160; If you try to shutdown from XenCenter, it will give you the option of unprotecting the VM and then shutting it down first.&amp;#160; Thus, accidental in-guest shutdowns wont result in downtime, but administrators can still stop a protected guest if they really want to.&lt;/li&gt;

&lt;li&gt;If you want to reboot a host when HA is enabled, XenCenter automatically uses the hypothetical planning calculation to determine if this would invalidate the failover plan.&amp;#160; If it doesn&amp;#8217;t affect it, then the host is shut down normally.&amp;#160; If the plan would be violated, but the &lt;em&gt;nhtol&lt;/em&gt; is greater than 1, XenCenter will give the administrator the option of lowering the &lt;em&gt;nhtol&lt;/em&gt; value by 1.&amp;#160; This reduces the overall resilience of the pool, but always ensures that at least one host failure will be tolerated.&amp;#160; When the host comes back up, the plan is automatically recalculated and the original &lt;em&gt;nhtol&lt;/em&gt; value restored if appropriate.&lt;/li&gt;

&lt;li&gt;If you try to apply a hotfix, then XenCenter will disable HA for the duration of the pool patching wizard.&amp;#160; It is important to manually keep an eye on hotfix application to ensure that host failures do not disrupt the operation of the pool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I hope this short article has given you a taster&amp;#8230; just kidding! This post is almost as long as my PhD thesis, but then, HA is a complex topic. Please do feel free to get back to me with comments and feedback about how we can improve it in the future releases, or if you just love it the way it is.&amp;#160; Many thanks to Dave Scott, Richard Sharp, Ewan Mellor and Hugh Warrington for their input to this article.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Shedding some light on XenApp on XenServer performance tuning</title>
   <link href="http://anil.recoil.org/2008/08/04/shedding-some-light-on-xenapp-on-xenserver-performance-tuning.html"/>
   <updated>2008-08-04T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2008/08/04/shedding-some-light-on-xenapp-on-xenserver-performance-tuning</id>
   <content type="html">&lt;p&gt;You won&amp;#8217;t be surprised to hear that we spend a lot of time improving &lt;a href='http://www.citrix.com/XenApp'&gt;XenApp&lt;/a&gt; performance when running on &lt;a href='http://www.citrix.com/XenServer'&gt;XenServer&lt;/a&gt;. Although there are some good benchmark comparisons available (such as the &lt;a href='http://community.citrix.com/x/_4ENAg'&gt;Tolly Group&lt;/a&gt; report), I still get a lot of customers asking about what the &amp;#8220;secret sauce&amp;#8221; is. I sat down with George Dunlap, the lead XenServer performance engineer to chat about the very first optimisation we did back in XenServer 4.0 last year.&lt;/p&gt;

&lt;p&gt;Before we dive in, we first need to explain how a normal operating system handles memory. George explains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Modern desktop and server processors don&amp;#8217;t access memory directly using its physical address. They use &amp;#8217;&lt;a href='http://en.wikipedia.org/Virtual_Memory'&gt;virtual memory&lt;/a&gt;&amp;#8217; to separate the addresses that processes use to read and write memory from the actual memory itself. This allows operating systems to hide from processes all the dirty details of how much memory there is, where in physical memory the process needs to write to, and so on.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;However, the actual processor still needs to translate from a &lt;a href='http://en.wikipedia.org/wiki/Virtual_address'&gt;virtual address&lt;/a&gt; to the physical memory address in order to actually read and write any memory. This translation is done with something called &lt;a href='http://en.wikipedia.org/wiki/Page_tables'&gt;page tables&lt;/a&gt;.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Page tables are used to implement virtual memory by mapping virtual addresses to physical addresses. The operating system constructs page tables using physical memory addresses, and then puts the physical address of the &amp;#8220;top-level&amp;#8221; page table into a hardware register called the &amp;#8216;base pointer&amp;#8217;. Then the processor will read these page tables to translate virtual addresses to physical addresses as needed, before reading and writing to physical memory.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most modern processor types have some sort of paging mechanism, although XenServer is specifically tuned for &lt;a href='http://en.wikipedia.org/wiki/X86-64'&gt;x86-64&lt;/a&gt; CPUs. An excellent book on the general topic is &lt;a href='http://en.wikipedia.org/wiki/Special:BookSources/0130313580'&gt;Modern Operating Systems&lt;/a&gt; by &lt;a href='http://www.cs.vu.nl/~ast/'&gt;Andrew Tanenbaum&lt;/a&gt;. When XenServer creates Windows VMs, it takes advantage of the &lt;a href='http://en.wikipedia.org/wiki/X86_virtualization'&gt;virtualization extensions&lt;/a&gt; in modern CPUs, which requires special memory handling in Xen. George explains this further:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;When we create a virtual machine, we virtualize the memory as well; that means that the guest operating system&amp;#8217;s idea of physical memory does not match up to real physical memory on the host. Traditionally, what the guest thinks of as physical memory is called &amp;#8220;physical memory&amp;#8221;, and what the hypervisor thinks of as physical memory is called &amp;#8220;machine memory&amp;#8221;. Since this terminology is a bit confusing, Xen tends to call what the guest thinks of as physical memory as &amp;#8220;guest physical&amp;#8221; memory, just to help make things more clear.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;This means that any fully-virtualized operating system, like Windows, will create page tables using guest physical memory, and will point the base pointer at the guest physical address of the top-level page table. Unfortunately, the hardware still needs to map from virtual memory address to machine addresses, not guest physical addresses.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;In order to allow this to happen, the hypervisor sets up &lt;b&gt;shadow page tables&lt;/b&gt;. These page tables are generated by the hypervisor are copies of the guest page tables, but with the guest physical addresses converted into machine physical addresses. The guest cannot access them directly, and they don&amp;#8217;t reside in the guest&amp;#8217;s physical memory; they&amp;#8217;re generated out of a pool of memory that the hypervisor allocates when a VM is created, called &amp;#8220;shadow page table memory&amp;#8221;.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;What this means is that whenever the guest operating system wants to map some new memory, after it writes the data into the page table but before it can actually use it, the hypervisor needs to translate the change to the guest page table into changes to the shadow page table. So any workload that involves a lot of this will necessarily involve the hypervisor a lot, which causes overhead.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So shadow page tables are our mechanism of giving a guest an interface which is identical to real hardware (so it doesn&amp;#8217;t need to be modified), but still intercepting changes before they reach the real hardware. You can find more details from the &lt;a href='http://www.xensource.com/files/summit_3/XenSummit_Shadow2.pdf'&gt;XenSummit 2006 talk&lt;/a&gt; or from the 2005 &lt;a href='http://www.cl.cam.ac.uk/research/srg/netos/papers/2005-migration-nsdi-pre.pdf'&gt;NSDI paper&lt;/a&gt;. So how is this all relevant to XenApp performance? Back to George&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;The hypervisor allocates a certain amount of memory for each VM to use for shadow page tables; this is called &lt;b&gt;shadow page table memory&lt;/b&gt;. As new page tables are created and old ones aren&amp;#8217;t used anymore, the hypervisor cycles through this shadow page table memory. When it needs a new page and there isn&amp;#8217;t enough, it will &amp;#8216;unshadow&amp;#8217; the guest page tables that haven&amp;#8217;t been used for the longest time to reclaim shadow memory, so that it can use more.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;We don&amp;#8217;t know ahead of time how much shadow memory a given workload will use, but we can estimate based on the amount of memory that the VM has. We allocate enough shadow memory for each page to be mapped once, more or less, then add an extra 50% to have some slack. For all the workloads we&amp;#8217;ve tested, that&amp;#8217;s been enough &amp;#8211; except XenApp.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;XenApp is the one workload we&amp;#8217;ve found that requires more shadow page table memory than our standard default. Because XenApp generally starts hundreds of copies of the same process, the same memory ends up mapped in hundreds of different processes. What happens when all of those processes are active is that XenServer is continually unshadowing one process&amp;#8217; page tables in order to shadow another process&amp;#8217; pagetables; only to have to re-shadow the original ones a second or two later when it runs again! This is called &lt;a href='http://en.wikipedia.org/wiki/Thrash_(computer_science)'&gt;thrashing&lt;/a&gt;, when there&amp;#8217;s not enough of a limited resource.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the bottleneck was discovered, the solution was simple. In XenServer 4.1, we created a special XenServer application template called &lt;em&gt;&quot;Citrix XenApp&quot;&lt;/em&gt;, which has an increased shadow multiplier that reserves more shadow memory for the guest when it starts. This is also a good example of how templates hide the complexities of performance tuning from the user, but still permitting custom modifications if they are required. For example, on your XenServer host with a VM called &amp;#8220;XenApp&amp;#8221;, you could view the shadow multiplier by using the CLI:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# xe vm-list name-label=XenApp params=HVM-shadow-multiplier
  HVM-shadow-multiplier ( RW)    : 4.000&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The same value is also available from XenCenter in the Optimization pane, but of course do remember that the default value was chosen through extensive testing and doesn&amp;#8217;t need to be changed. Most of the other templates in XenServer also have carefully tuned settings (e.g. the hardware platform flags) to ensure smooth running, or in the case of Linux templates, to support &lt;a href='http://docs.xensource.com/XenServer/4.1.0/1.0/en_gb/sdk.html#id2553443'&gt;para-virtual installation&lt;/a&gt;. This is why it&amp;#8217;s so important that you not use the &lt;em&gt;&quot;Other Install Media&quot;&lt;/em&gt; template in preference of a more specialised one!&lt;/p&gt;

&lt;p&gt;I mentioned at the beginning of this post that this was the first of many XenApp optimisations. We&amp;#8217;ve just released the &lt;a href='https://www.citrix.com/English/ss/downloads/details.asp?downloadId=1679827&amp;amp;productId=683148'&gt;public beta&lt;/a&gt; of the latest XenServer (&amp;#8220;Orlando&amp;#8221;) which is even faster. The story of what those improvements are, and the tools which George and his team uses to analyze the inner workings of Xen, are a topic for a future post. For now, get downloading XenServer and start virtualizing your XenApp installations! Or if you&amp;#8217;re feeling inspired, go over to &lt;a href='http://xen.org/'&gt;xen.org&lt;/a&gt;, check out the source, and get coding&amp;#8230;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Installing Ubuntu on XenServer</title>
   <link href="http://anil.recoil.org/2008/07/02/installing-ubuntu-on-xenserver.html"/>
   <updated>2008-07-02T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2008/07/02/installing-ubuntu-on-xenserver</id>
   <content type="html">&lt;p&gt;I thought I&amp;#8217;d kick off my Citrix blog with a question I get pretty often from Linux enthusiasts: how to install unsupported Linux distributions on XenServer 4.1.&lt;/p&gt;

&lt;p&gt;The most common solution people find is to use the &amp;#8220;Other Install Media&amp;#8221; template, insert the distribution installation CD, and find that the mouse cursor doesn&amp;#8217;t work when they boot into X11. The reason for this is that they are using the hardware-assisted emulation mode of installing Linux. In this mode (dubbed &amp;#8220;HVM&amp;#8221;), all input and output is emulated, and in particular the mouse interface uses the USB tablet interface. If the distribution doesn&amp;#8217;t include a driver for USB tablets, then no mouse will appear.&lt;/p&gt;

&lt;p&gt;Windows guests run at high-speed in HVM mode due to the installation of the XenServer tools which install &lt;a href='http://xen.org/files/summit_3/xen-pv-drivers.pdf'&gt;high-speed drivers&lt;/a&gt;, but these are not necessary for Linux distributions since they can be run in &lt;a href='http://en.wikipedia.org/wiki/Paravirtualization'&gt;para-virtualized&lt;/a&gt; mode (dubbed &amp;#8220;PV&amp;#8221;). This involves obtaining a Xen-enabled PV kernel from the distribution, and modifying the VM record in XenServer to boot into this kernel instead of HVM mode. The XenServer built-in templates for popular distributions such as RHEL, CentOS or SUSE Linux already automate all this and are in PV mode from the installer onwards.&lt;/p&gt;

&lt;p&gt;In the remainder of this post, I&amp;#8217;ll explain how to take a distribution without direct support (&lt;a href='http://www.ubuntu.com/'&gt;Ubuntu&lt;/a&gt; &lt;a href='https://wiki.ubuntu.com/HardyHeron'&gt;8.04&lt;/a&gt;), get it installed in HVM mode on XenServer 4.1, and convert it to PV mode with a XenCenter graphical console.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Download the &quot;&lt;a href='http://www.ubuntu.com/GetUbuntu/download'&gt;Alternative Installation CD&lt;/a&gt;&quot;.  The main installation CD uses graphical mode, which won't install as well in HVM mode due to the use of esoteric 16-bit mode instructions for the graphics operations.  The 16-bit emulation mechanisms vary between processors (with better support on AMD chips, and a software instruction emulator required on Intel VT chips).  However, the Ubuntu alternate CD uses a text-based installer which works fine.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;Create a new VM on the XenServer 4.1 host using the &quot;Windows Server 2003&quot; template.  This template is set up with a sensible set of hardware emulation flags and default disks, and so is a good base for the HVM installation of Ubuntu as well.  Attach the Ubuntu ISO you just downloaded to the VM, and proceed to install Ubuntu as normal.  You should install it onto the first disk, to make the subsequent steps in this guide easier.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;When the installation is finished, reboot the VM (don't forget to detach the installation ISO first).  It should boot up in HVM mode into the graphical login screen.  The XenCenter display will show it as not being optimized, which is fine.  At this stage, I prefer to work via a remote command-line using SSH.  Open up a Terminal from Ubuntu, and run &quot;&lt;tt&gt;sudo apt-get install openssh-server&lt;/tt&gt;&quot;.  Then find out the VM's IP address with &quot;&lt;tt&gt;ifconfig eth0&lt;/tt&gt;&quot;, and then connect to it remotely.  Alternatively, you can continue to type in the commands directly into the terminal as well.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;On the Ubuntu guest, you now need to install the latest Xen version of the Ubuntu kernel:
	&lt;ul&gt;
		&lt;li&gt;Install the Linux kernel virtual package with &quot;&lt;tt&gt;sudo apt-get install linux-image-xen&lt;/tt&gt;&quot;.  This is a virtual package which pulls in the latest Xen kernel and modules, in my case &lt;tt&gt;2.6.24.19.21&lt;/tt&gt;.&lt;/li&gt;
		&lt;li&gt;You now need to workaround a &lt;a href='http://www.mail-archive.com/grub-devel@gnu.org/msg06024.html'&gt;bug&lt;/a&gt; in grub.  Due to the switch in recent versions of Linux to work with the hypervisor-independent &lt;a href='http://xen.xensource.com/files/xensummit_4/xen-paravirt_ops_Fitzhardinge.pdf'&gt;paravirt_ops&lt;/a&gt; interface, &lt;tt&gt;update-grub&lt;/tt&gt; doesn't update the grub configuration with your newly installed Xen kernel.  To fix this:
		&lt;ul&gt;
			&lt;li&gt;Open &lt;tt&gt;/boot/grub/menu.lst&lt;/tt&gt; in your favourite editor.&lt;/li&gt;
			&lt;li&gt;Scroll to the bottom to the kernel list, and find the entry which looks like:
&lt;div style='border-width: 1px;' class='preformatted panel'&gt;&lt;div class='preformattedContent panelContent'&gt;
&lt;pre&gt;title           Ubuntu 8.04, kernel 2.6.24-16-generic
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.24-16-generic root=UUID=&amp;lt;uuid&amp;gt; ro quiet splash
initrd          /boot/initrd.img-2.6.24-16-generic
quiet
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
			&lt;li&gt;Add a new entry which is similar to this, but change all references to the &lt;tt&gt;2.6.24-16-generic&lt;/tt&gt; to the Xen kernel.  In &lt;tt&gt;/boot&lt;/tt&gt; I have &lt;tt&gt;vmlinuz-2.6.24-19-xen&lt;/tt&gt;, so my new entry looks like:
&lt;div style='border-width: 1px;' class='preformatted panel'&gt;&lt;div class='preformattedContent panelContent'&gt;
&lt;pre&gt;title           Ubuntu 8.04, kernel 2.6.24-19-xen
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.24-19-xen root=UUID=&amp;lt;uuid&amp;gt; ro quiet splash
initrd          /boot/initrd.img-2.6.24-19-xen
quiet
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
			&lt;li&gt;Also edit the &lt;tt&gt;default&lt;/tt&gt; entry in the &lt;tt&gt;menu.lst&lt;/tt&gt; to match the number of the kernel you just added.  I set mine to 3, since it is the fourth entry in the list and the indexing starts from 0.&lt;/li&gt;
		&lt;/ul&gt;
		&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;When this is done, shut down the guest but do not reboot it just yet.  You first need to edit the VM record for your Ubuntu VM to convert it to PV boot mode.  From the control domain console of your XenServer:
	&lt;ul&gt;
		&lt;li&gt;Determine the UUID of the Ubuntu VM by using the &lt;tt&gt;xe&lt;/tt&gt; CLI:
		&lt;ul&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-list name-label=Ubuntu params=uuid --minimal&lt;/tt&gt; : this will print out the UUID of the VM named &quot;Ubuntu&quot;.  If you are logged into the control domain, pressing the &lt;tt&gt;&amp;lt;tab&amp;gt;&lt;/tt&gt; key will perform auto-completion of UUIDs in subsequent XE commands, so you don't need to keep typing it in every time!&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-param-set uuid=&amp;lt;uuid&amp;gt; HVM-boot-policy=&lt;/tt&gt; : this will clear the HVM boot mode from the VM.&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-param-set uuid=&amp;lt;uuid&amp;gt; PV-bootloader=pygrub&lt;/tt&gt; : this will switch the VM to using to the pygrub bootloader which starts the guest in PV mode by examining its filesystem for kernel.&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;vm vm-param-set uuid=&amp;lt;uuid&amp;gt; PV-args=&quot;console=tty0 xencons=tty&quot;&lt;/tt&gt; : this configures the kernel boot arguments to display the login console on the correct TTY, so that it shows up in the XenCenter console.&lt;/li&gt;
		&lt;/ul&gt;
		&lt;/li&gt;
		&lt;li&gt;Next, you need to flag the root disk of the VM as bootable so that pygrub knows where to look for the PV kernel:
		&lt;ul&gt;
			&lt;li&gt;&lt;tt&gt;xe vm-disk-list uuid=&amp;lt;uuid&amp;gt;&lt;/tt&gt; and look for the UUID of the VBD for the disk.  VBD stands for &quot;Virtual Block Device&quot; and represents how to map the virtual disk into the virtual machine.&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;xe vbd-param-set uuid=&amp;lt;vbd uuid&amp;gt; bootable=true&lt;/tt&gt; will set the root disk VBD to be bootable.&lt;/li&gt;
		&lt;/ul&gt;
		&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;You should be all set now!  If you boot up the Ubuntu VM, it should start up in text-mode with the high-speed PV kernel.  If it doesn't work due to an incorrect grub configuration, you can use the &lt;tt&gt;xe-edit-bootloader&lt;/tt&gt; script in the XenServer control domain to edit the &lt;tt&gt;grub.conf&lt;/tt&gt; until it works.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;The next step is to install the XenServer tools within the guest, so that metrics such as the network interface IP addresses are recorded and reported from XenCenter.  To do this:
	&lt;ul&gt;
		&lt;li&gt;Due to a portability issues with the default shell in Ubuntu (&lt;a href='http://en.wikipedia.org/wiki/Debian_Almquist_shell'&gt;dash&lt;/a&gt;), you will need to replace it by: &lt;tt&gt;sudo apt-get -y install bash &amp;amp;&amp;amp; sudo dpkg-reconfigure dash&lt;/tt&gt;.  We've actually fixed this issue in future releases of XenServer, but for XenServer 4.1 you will need to use &lt;tt&gt;bash&lt;/tt&gt;.&lt;/li&gt;
		&lt;li&gt;Attach the XenServer Tools ISO into the VM, and mount it into the guest with &lt;tt&gt;sudo mount /dev/xvdd /mnt&lt;/tt&gt;&lt;/li&gt;
		&lt;li&gt;Install the tools with &lt;tt&gt;sudo dpkg -i /mnt/Linux/xe-guest-utilities_4.1.0-257_i386.deb&lt;/tt&gt;.&lt;/li&gt;
		&lt;li&gt;The warnings about the VM being unoptimized should disappear, and additional information such as the IP address of the guest should appear in XenCenter.&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;
	&lt;li&gt;In order to access the Ubuntu installation via the graphical console, you need to configure it to run &lt;a href='http://www.realvnc.com/'&gt;VNC&lt;/a&gt; on the external network interface.  XenCenter polls the guest to see if it is listening on the VNC port 5900, and offers the option to switch to the graphical console if it finds it.  I followed the excellent instructions on this &lt;a href='http://ubuntuforums.org/showpost.php?p=4963842&amp;amp;postcount=1'&gt;forum post&lt;/a&gt;.  To summarise them:
	&lt;ul&gt;
		&lt;li&gt;&lt;tt&gt;sudo apt-get install vnc4server xinetd&lt;/tt&gt; : to install the required packages&lt;/li&gt;
		&lt;li&gt;Edit &lt;tt&gt;/etc/gdm/gdm.conf&lt;/tt&gt; and uncomment the &lt;tt&gt;RemoteGreeter=/usr/lib/gdm/gdmlogin&lt;/tt&gt; line, set the key &lt;tt&gt;Enable=true&lt;/tt&gt; in the &lt;tt&gt;&lt;span class='error'&gt;&amp;#91;xdcmp&amp;#93;&lt;/span&gt;&lt;/tt&gt; section.&lt;/li&gt;
		&lt;li&gt;Install a new service file for &lt;tt&gt;xinetd&lt;/tt&gt; into &lt;tt&gt;/etc/xinetd.d/Xvnc&lt;/tt&gt; with the following contents:
&lt;div style='border-width: 1px;' class='preformatted panel'&gt;&lt;div class='preformattedContent panelContent'&gt;
&lt;pre&gt;service Xvnc
{
  type = UNLISTED
  disable = no
  socket_type = stream
  protocol = tcp
  wait = no
  user = nobody
  server = /usr/bin/Xvnc
  server_args = -inetd -query localhost -geometry 1024x768  -depth 16 -cc 3 -once -SecurityTypes=none -extension XFIXES
  port = 5900
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
		&lt;li&gt;The major difference from the forum poster is to run it on port 5900, and not to restrict it to just localhost (since XenCenter also needs to connect to it).&lt;/li&gt;
		&lt;li&gt;Finally, restart the &lt;tt&gt;xinetd&lt;/tt&gt; service by running &lt;tt&gt;sudo /etc/init.d/xinetd restart&lt;/tt&gt;.&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Once you're done with this installation, you can shut down the VM and convert it to a template.  Any exports or clones will continue to run in PV mode, since the XenServer XVA export format records all of the metadata required to re-create the VM records.&lt;/p&gt;&lt;p&gt;Enjoy the Ubuntu on XenServer experience!  Remember to report any issues you have with the in-guest packages on the Ubuntu support forums, or just give them positive feedback.&lt;/p&gt;&lt;p&gt;PS: many thanks to Andrew Peace and Ian Campbell for assistance.  May their Linux beards remain long and uncut.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Parsing EXIF/IPTC photo tags using pyexiv2 on Leopard</title>
   <link href="http://anil.recoil.org/2008/04/17/parsing-exif-iptc-photo-tags-using-pyexiv2-on-leopard.html"/>
   <updated>2008-04-17T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2008/04/17/parsing-exif-iptc-photo-tags-using-pyexiv2-on-leopard</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve been looking around at refreshing my current photo gallery to make it easier to update, since I&amp;#8217;m around 1000 photos behind over the last year. Part of making it easier to use is to adopt an &lt;a href='http://www.apple.com/aperture'&gt;Aperture&lt;/a&gt;-based system of marking the metadata directly in the image itself, and figuring out how to render so many pictures more effectively in my &lt;a href='http://anil.recoil.org/gallery/'&gt;gallery&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The best library I could find to do the job is &lt;a href='http://www.exiv2.org'&gt;Exiv2&lt;/a&gt; and its associated Python bindings &lt;a href='http://tilloy.net/dev/pyexiv2/'&gt;pyexiv2&lt;/a&gt;. They use the rather complex &lt;a href='http://www.boost.org/doc/libs/1_35_0/libs/python/doc/index.html'&gt;Boost.Python&lt;/a&gt; bindings, which are a total pain to compile on MacOS X Leopard.&lt;/p&gt;

&lt;p&gt;In order to get it to work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use the latest &lt;a href='http://www.finkproject.org'&gt;Fink&lt;/a&gt; to install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;python25&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;boost1.34.python25&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;libexiv2&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;scons&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Download the latest &lt;a href='http://tilloy.net/dev/pyexiv2/download.htm'&gt;pyexiv2 distribution&lt;/a&gt;, extract it, and drop in my &lt;a href='http://anil.recoil.org/files/pyexiv2/Makefile'&gt;exiv2 Leopard Makefile&lt;/a&gt; into the extracted directory.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Type in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;sudo make install&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Test it out by running python2.5 and experimenting with importing pyexiv2 (see the pyexiv2 &lt;a href='http://tilloy.net/dev/pyexiv2/developers.htm'&gt;developer guide&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;ll tidy this up into a fink package sometime, but for now I want to press on with finishing my &lt;a href='http://www.djangoproject.org/'&gt;Django&lt;/a&gt; experiments.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Sushi, Seattle and Seahawks</title>
   <link href="http://anil.recoil.org/2007/04/11/sushi-seattle-and-seahawks.html"/>
   <updated>2007-04-11T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2007/04/11/sushi-seattle-and-seahawks</id>
   <content type="html">&lt;a rel='lightbox' title='Random view of Redmond countryside' href='http://anil.recoil.org/gallery/images/redmond-view-1-large.jpg'&gt;&lt;img style='float:right' src='http://anil.recoil.org/gallery/images/redmond-view-1-medium.jpg' alt='Random view of Redmond countryside' /&gt; &lt;/a&gt;
&lt;p&gt;So I&amp;#8217;m hanging at the &lt;a href='http://www.xensource.com/'&gt;XenSource&lt;/a&gt; Redmond office for a few days, and munching on delicious sushi at &lt;a href='http://www.florestaurant.com/index.htm'&gt;Flo&lt;/a&gt;, and it turns out that the dude behind us was none other than &lt;a href='http://www.nfl.com/players/playerpage/12429'&gt;Matt Hasselbeck&lt;/a&gt;! It seems like only two years ago that I was cheering on the &lt;a href='http://www.steelers.com/'&gt;Pittsburgh Steelers&lt;/a&gt; and &lt;a href='http://en.wikipedia.org/wiki/Jerome_Bettis'&gt;the Bus&lt;/a&gt; as they owned the &lt;a href='http://www.seahawks.com/'&gt;Seahawks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, I only realised my brief brush with celebrity on our way out of the restaurant, which also probably saved me from saying something stupid to him. As if! But anyway, the, err, moral of this post is that you must check out Flo Sushi if you&amp;#8217;re in Seattle and eat the spider roll, it&amp;#8217;s awesome.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Karnatik Jazz, Live Painting, and such things...</title>
   <link href="http://anil.recoil.org/2007/04/08/karnatik-jazz-live-painting-and-such-things.html"/>
   <updated>2007-04-08T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2007/04/08/karnatik-jazz-live-painting-and-such-things</id>
   <content type="html">&lt;p&gt;Had a great evening out in San Francisco on Friday, when we visited the &lt;a href='http://www.redpoppyarthouse.org/'&gt;Red Poppy Art House&lt;/a&gt; on Folsom Street to check out a really unique Jazz experience.&lt;/p&gt;

&lt;p&gt;The boys from &lt;a href='http://www.vidyamusic.com/'&gt;VidyA&lt;/a&gt; recently took up an artist-in-residence position there, and performed their fusion of traditional Indian &lt;a href='http://www.karnatik.com/'&gt;Karnatik&lt;/a&gt; music with modern Jazz pieces. They&amp;#8217;ve been making some &lt;a href='http://sfgate.com/cgi-bin/article.cgi?f=/c/a/2007/01/10/DDGTFNF6OE1.DTL&amp;amp;type=music'&gt;waves&lt;/a&gt; in the SF Jazz scene already it seems, and to top it all of, the owner of the art house did a live painting session during the performance. The audience passed out random bits of stuff, and he incorporated it into a piece done over the course of an evening. Talk about artistic overload!&lt;/p&gt;

&lt;p&gt;Love the area as well; there&amp;#8217;s a nice friendly &lt;a href='http://www.folsomstreetcoffee.com/'&gt;coffee-house&lt;/a&gt; down the road (which is pretty much my only criteria, apart from not getting shot and such).&lt;/p&gt;
&lt;table width='90%' align='center'&gt;
&lt;tr&gt;
&lt;td class='bimg'&gt;
&lt;a href='http://anil.recoil.org/gallery/2007/04/07/index.html#sf-mission-4'&gt;&lt;img width='140' border='0' src='http://anil.recoil.org/gallery/images/sf-mission-4-medium.jpg' alt='My school was never this cool.' height='140' /&gt;&lt;/a&gt;&lt;br /&gt;My school was never this cool.&lt;/td&gt;
&lt;td class='bimg'&gt;&lt;a href='http://anil.recoil.org/gallery/2007/04/07/index.html#sf-mission-8'&gt;&lt;img width='140' border='0' src='http://anil.recoil.org/gallery/images/sf-mission-8-medium.jpg' alt='The area was a mix of Latino and African, it seemed' height='140' /&gt;&lt;/a&gt;&lt;br /&gt;The area was a mix of Latino and African, it seemed&lt;/td&gt;
&lt;td class='bimg'&gt;&lt;a href='http://anil.recoil.org/gallery/2007/04/07/index.html#sf-mission-9'&gt;&lt;img width='140' border='0' src='http://anil.recoil.org/gallery/images/sf-mission-9-medium.jpg' alt='And in the Red Poppy Art House, eclectic art abounds' height='140' /&gt;&lt;/a&gt;&lt;br /&gt;And in the Red Poppy Art House, eclectic art abounds&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</content>
 </entry>
 
 <entry>
   <title>Core stability exercising</title>
   <link href="http://anil.recoil.org/2007/04/08/core-stability-exercising.html"/>
   <updated>2007-04-08T00:00:00+01:00</updated>
   <id>http://anil.recoil.org/2007/04/08/core-stability-exercising</id>
   <content type="html">&lt;p&gt;It&amp;#8217;s been a wierd exercise year; I went from hard-core powerlifting (go 220lb bench!), to playing a lot of badminton and tennis, and then ending off the PhD era with breaking my knee (details not suitable for blog publication). &lt;br /&gt; &lt;a rel='lightbox' title='Ajay having a little stretch' href='http://anil.recoil.org/gallery/images/ajay-stretch-1-large.jpg'&gt;&lt;img style='float:right' src='http://anil.recoil.org/gallery/images/ajay-stretch-1-medium.jpg' alt='Ajay having a nice stretch' /&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As anyone it&amp;#8217;s happened to knows, a knee injury is really annoying to recover from as it feels really &amp;#8220;wobbly&amp;#8221; for ages and can&amp;#8217;t quite be trusted. I&amp;#8217;ve been doing physio on it myself for about half a year now, and can finally run around for 5km or so without too much discomfort, although &lt;a href='http://www.camyoga.co.uk/'&gt;yoga&lt;/a&gt; and &lt;a href='http://www.capoeira-cambridge.co.uk/'&gt;Capoeria&lt;/a&gt; are perhaps a few more months away.&lt;/p&gt;

&lt;p&gt;But then, the Forrest Gump-class runner and ex-officemate &lt;a href='http://www.cl.cam.ac.uk/~ach61/'&gt;Alex Ho&lt;/a&gt; pointed out &lt;em&gt;&lt;a href='http://www.srcf.ucam.org/cuhh/linksandresources/core-stability.pdf'&gt;these amazing exercises&lt;/a&gt;&lt;/em&gt; by the captain of the &lt;a href='http://www.srcf.ucam.org/cuhh/'&gt;CUH&amp;amp;H&lt;/a&gt; running team in Cambridge. They all emphasise smooth movement and core strength without the need for heavy weights, so can be done while travelling as well. So highly recommended, that even little Ajay &lt;em&gt;(right)&lt;/em&gt; is trying them out!&lt;/p&gt;</content>
 </entry>
 
 
</feed>
