240 likes | 393 Views
F# for Architects Hitting the Sweet Spot. Chris Smith, Microsoft Twitter @ aChrisSmith http://blogs.msdn.com/chrsmith. Why this talk will be awesome. F# Facts. Commonly known F# facts “Write tomorrow’s legacy code today in C#” F# will parallelize things for free
E N D
F# for ArchitectsHitting the Sweet Spot Chris Smith, Microsoft Twitter @aChrisSmith http://blogs.msdn.com/chrsmith
F# Facts • Commonly known F# facts • “Write tomorrow’s legacy code today in C#” • F# will parallelize things for free • Functional programming is the future • F# developers are smarter and better looking that other programmers • You should rewrite all your ASP.NET apps in F#
Agenda • Before you get started • F#’s Strengths • F#’s Weaknesses • Bottom Line
F# in Five Minutes Language Tools First-class language in VS2010* F# Interactive Window F# PowerPack • Multi-paradigm language • Type inferred • Just another .NET language F# = Fun
F# Interop F# can do… … as well as Function values Discriminated unions Pattern matching Lazy evaluation Records Lists Tuples Computation expressions / Monads (Über-geek stuff) • Classes • Generics • Delegates • Enumerations • Structures • P/Invoke
Microsoft .NET Ecosystem • Tools & Languages • Visual Studio • Expression Studio • VB, C#, F#, Iron R/P, … • Platforms • XNA • Compact Framework • Visual Studio Tools for Office • Silverlight
Functional vs. Object-Oriented FP : small :: OO : large
Technical Computing • Simulation • Computational Finance • Large-scale Data Processing
Language Oriented Programming • Writing Parsers • Augmenting F# Code • Creating New Languages • Quotations (Expression Trees)
Parallel Programming* • Immutable by default • Parallel Extensions to .NET • Task Parallel Library • Concurrent Data Structures • Asynchronous Workflows *Parallel, Asynchronous, Concurrent, and Reactive Programming
Asynchronous Programming Model using System; using System.IO; using System.Threading; public class BulkImageProcAsync { public const String ImageBaseName = "tmpImage-"; public const intnumImages = 200; public const intnumPixels = 512 * 512; // ProcessImage has a simple O(N) loop, and you can vary the number // of times you repeat that loop to make the application more CPU- // bound or more IO-bound. public static intprocessImageRepeats = 20; // Threads must decrement NumImagesToFinish, and protect // their access to it through a mutex. public static intNumImagesToFinish = numImages; public static Object[] NumImagesMutex = new Object[0]; // WaitObject is signalled when all image processing is done. public static Object[] WaitObject = new Object[0]; public class ImageStateObject { public byte[] pixels; public intimageNum; public FileStreamfs; } public static void ReadInImageCallback(IAsyncResultasyncResult) { ImageStateObject state = (ImageStateObject)asyncResult.AsyncState; Stream stream = state.fs; intbytesRead = stream.EndRead(asyncResult); if (bytesRead != numPixels) throw new Exception(String.Format ("In ReadInImageCallback, got the wrong number of " + "bytes from the image: {0}.", bytesRead)); ProcessImage(state.pixels, state.imageNum); stream.Close(); // Now write out the image. // Using asynchronous I/O here appears not to be best practice. // It ends up swamping the threadpool, because the threadpool // threads are blocked on I/O requests that were just queued to // the threadpool. FileStreamfs = new FileStream(ImageBaseName + state.imageNum + ".done", FileMode.Create, FileAccess.Write, FileShare.None, 4096, false); fs.Write(state.pixels, 0, numPixels); fs.Close(); // This application model uses too much memory. // Releasing memory as soon as possible is a good idea, // especially global state. state.pixels = null; fs = null; // Record that an image is finished now. lock (NumImagesMutex) { NumImagesToFinish--; if (NumImagesToFinish == 0) { Monitor.Enter(WaitObject); Monitor.Pulse(WaitObject); Monitor.Exit(WaitObject); } } } public static void ProcessImagesInBulk() { Console.WriteLine("Processing images... "); long t0 = Environment.TickCount; NumImagesToFinish = numImages; AsyncCallbackreadImageCallback = new AsyncCallback(ReadInImageCallback); for (inti = 0; i < numImages; i++) { ImageStateObject state = new ImageStateObject(); state.pixels = new byte[numPixels]; state.imageNum = i; // Very large items are read only once, so you can make the // buffer on the FileStream very small to save memory. FileStreamfs = new FileStream(ImageBaseName + i + ".tmp", FileMode.Open, FileAccess.Read, FileShare.Read, 1, true); state.fs = fs; fs.BeginRead(state.pixels, 0, numPixels, readImageCallback, state); } // Determine whether all images are done being processed. // If not, block until all are finished. boolmustBlock = false; lock (NumImagesMutex) { if (NumImagesToFinish > 0) mustBlock = true; } if (mustBlock) { Console.WriteLine("All worker threads are queued. " + " Blocking until they complete. numLeft: {0}", NumImagesToFinish); Monitor.Enter(WaitObject); Monitor.Wait(WaitObject); Monitor.Exit(WaitObject); } long t1 = Environment.TickCount; Console.WriteLine("Total time processing images: {0}ms", (t1 - t0)); } }
F# Asynchronous Workflows Open the file, synchronously Equivalent F# code (same perf) Read from the file, asynchronously let ProcessImageAsync(i) = async{letinStream =File.OpenRead(sprintf"source%d.jpg"i) let!pixels =inStream.AsyncRead(numPixels) letpixels' =TransformImage(pixels,i) letoutStream=File.OpenWrite(sprintf"result%d.jpg"i) do!outStream.AsyncWrite(pixels') doConsole.WriteLine"done!" } letProcessImagesAsync() = Async.Run (Async.Parallel [foriin1 .. numImages->ProcessImageAsync(i) ]) This object coordinates Write the result, asynchronously Generate the tasks and queue them in parallel “!” = “asynchronous”
F#’s not-as-strong-but-they-are-still-strengths • Presentation Layer • Object-oriented Hierarchies • ASP.NET*
Training Your Team • F#: Not for eggheads • Pay attention to what you hear • “Oh, it is just like C#” • “It is too simplistic for real-world development” • “Functional programming hurts my brain”
Maintenance Costs • Code Maintenance • Terse syntax matters! • Idiomatic vs. non-idiomatic code • Deploying F# Tools and Applications
How to Get F# • Download the May, 2009 CTP for Visual Studio 2008 from http://fsharp.net • Get Visual Studio 2010 Beta1 from http://msdn.com • Run F# on Linux via Mono http://mono-project.com
Resources • Books • Programming F#, O’Reilly (November, 2009) • Expert F#, Apress 2007 • Blogs • F# Team blogs • http://fsharp.net • Bugging other people • http://hubfs.net • http://stackoverflow.com
Thanks for your time! Questions?