f# server-side programming
DESCRIPTION
An F# presentation that I done a few years ago.TRANSCRIPT
![Page 1: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/1.jpg)
F# Server side programming
Dave ThomasMoiraeSoftware.comtwitter.com/7sharp9
![Page 2: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/2.jpg)
F# Server based programming
Why F#• Concise succinct code
• Advanced asynchronous support
• Language Orientated Programming
• Generic by default
• Immutable by default
![Page 3: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/3.jpg)
Fundamental Concepts
• Pure Functions– No side effects– memoization
• Immutability– No threading issues
• Lambda expressions• Higher order functions• Recursion
![Page 4: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/4.jpg)
Patterns and Practices
C#• Inheritance• Polymorphism
F#• Higher order functions• Type augmentation
![Page 5: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/5.jpg)
Patterns / similarities
• Discriminated unions -> Small class hierarchies
• Higher Order Functions -> Command Pattern
• Fold -> Visitor pattern
![Page 6: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/6.jpg)
A comparison of styles
F#• 1 source file• 43 lines• 2 types
C#• 2 source files• 166 lines• 2 type
75% reduction in code
![Page 7: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/7.jpg)
C# ObjectPool
![Page 8: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/8.jpg)
F# ObjectPool//Agent alias for MailboxProcessortype Agent<'T> = MailboxProcessor<'T>
///One of three messages for our Object Pool agenttype PoolMessage<'a> = | Get of AsyncReplyChannel<'a> | Put of 'a | Clear of AsyncReplyChannel<List<'a>>
/// Object pool representing a reusable pool of objectstype ObjectPool<'a>(generate: unit -> 'a, initialPoolCount) = let initial = List.init initialPoolCount (fun (x) -> generate()) let agent = Agent.Start(fun inbox -> let rec loop(x) = async { let! msg = inbox.Receive() match msg with | Get(reply) -> let res = match x with | a :: b -> reply.Reply(a);b | [] as empty-> reply.Reply(generate());empty return! loop(res) | Put(value)-> return! loop(value :: x) | Clear(reply) -> reply.Reply(x) return! loop(List.empty<'a>) } loop(initial))
/// Clears the object pool, returning all of the data that was in the pool. member this.ToListAndClear() = agent.PostAndAsyncReply(Clear)
/// Puts an item into the pool member this.Put(item ) = agent.Post(item)
/// Gets an item from the pool or if there are none present use the generator member this.Get(item) = agent.PostAndAsyncReply(Get)
![Page 9: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/9.jpg)
F# - Fracture IO
Open source high performance Socket, Pipeline, and agent library
![Page 10: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/10.jpg)
Sockets
2 Models of Operation
• AsyncResult Model
• SocketAsyncEventArgs Model
![Page 11: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/11.jpg)
IAsyncResults ModelPros• Well documented API• Can be simplified with helpers in
Asynchronous workflows in F#• Fast to get an initial result
Cons• Allocation of IAsyncResult on every Operation• Consumes more CPU for each send and receive operation
![Page 12: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/12.jpg)
F# AsyncResult
![Page 13: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/13.jpg)
SocketAsyncEventArgs Model
Pros• Less memory allocations• Better performance• Closer to the metal
Cons• Not a well understood or documented API• Can be complex to get right
![Page 14: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/14.jpg)
Performance Differences
• 5 minute test
• 50 clients connecting to the server
• 15ms interval between each one
• Server sends each client a 128 byte message every 100ms
• Total of 500 messages per second
Test Harness
![Page 15: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/15.jpg)
CPU & Threads
SocketAsyncEventArgs IAsyncResult
![Page 16: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/16.jpg)
MemorySocketAsyncEventArgs IAsyncResult
![Page 17: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/17.jpg)
Garbage collectionSocketAsyncEventArgs IAsyncResult
![Page 18: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/18.jpg)
Fracture Socket Implementation
![Page 19: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/19.jpg)
Agents
• Provide a message passing mechanism
• Agents read and respond to a queue of messages
• Typically a discriminated union is used to describe messages
![Page 20: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/20.jpg)
Introducing Fracture-IO
• High performance Socket library
• Highly compositional pipeline library
![Page 21: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/21.jpg)
Pipelines
• Closed Pipelines– Tomas Petricek• Image Processing Pipeline
• Open Pipelines– Pipelets
![Page 22: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/22.jpg)
Closed Pipelines
![Page 23: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/23.jpg)
Image Processing Pipeline
1: // Phase 1: Load images from disk and put them into a queue 2: let loadImages = async { 3: let clockOffset = Environment.TickCount 4: let rec numbers n = seq { yield n; yield! numbers (n + 1) } 5: for count, img in fileNames |> Seq.zip (numbers 0) do 6: let info = loadImage img sourceDir count clockOffset 7: do! loadedImages.AsyncAdd(info) } 8: 9: // Phase 2: Scale to a thumbnail size and add frame10: let scalePipelinedImages = async {11: while true do 12: let! info = loadedImages.AsyncGet()13: scaleImage info14: do! scaledImages.AsyncAdd(info) }
1: let loadedImages = new BlockingQueueAgent<_>(queueLength)2: let scaledImages = new BlockingQueueAgent<_>(queueLength) 3: let filteredImages = new BlockingQueueAgent<_>(queueLength)
1: // Phase 4: Display images as they become available 2: let displayPipelinedImages = async { 3: while true do 4: let! info = filteredImages.AsyncGet() 5: info.QueueCount1 <- loadedImages.Count 6: info.QueueCount2 <- scaledImages.Count 7: info.QueueCount3 <- filteredImages.Count 8: displayImage info } 9: 10: // Start workflows that implement pipeline phases11: Async.Start(loadImages, cts.Token)12: Async.Start(scalePipelinedImages, cts.Token)13: Async.Start(filterPipelinedImages, cts.Token)14: try Async.RunSynchronously(displayPipelinedImages, cancellationToken = cts.Token)15: with :? OperationCanceledException -> ()
![Page 24: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/24.jpg)
Open Pipelines
Advantages• Composability• Reusability• Can be used at any stage of processing• Separation of concerns• Flexible routing arrangements i.e. round robin, multicast,
content based routing
Disadvantages• Pipeline stages need to be balanced• Developers can have trouble debugging and visualizing
![Page 25: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/25.jpg)
Pipelets Implementation
![Page 26: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/26.jpg)
Pipelets in use
![Page 27: F# Server-side programming](https://reader035.vdocuments.mx/reader035/viewer/2022062405/5585a8b2d8b42ae3228b4c56/html5/thumbnails/27.jpg)
Future Directions
• Distributed Pipelets– Wave Pipelines
– Synchronous buffered Pipeline
• Advanced agent based programming- Supervision
- Pooling
- Control Messages