f# server-side programming

27
F# Server side programming Dave Thomas MoiraeSoftware.com t witter.com/7sharp9

Upload: 7sharp9

Post on 21-Jun-2015

1.187 views

Category:

Technology


0 download

DESCRIPTION

An F# presentation that I done a few years ago.

TRANSCRIPT

Page 1: F# Server-side programming

F# Server side programming

Dave ThomasMoiraeSoftware.comtwitter.com/7sharp9

Page 2: F# Server-side programming

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

Fundamental Concepts

• Pure Functions– No side effects– memoization

• Immutability– No threading issues

• Lambda expressions• Higher order functions• Recursion

Page 4: F# Server-side programming

Patterns and Practices

C#• Inheritance• Polymorphism

F#• Higher order functions• Type augmentation

Page 5: F# Server-side programming

Patterns / similarities

• Discriminated unions -> Small class hierarchies

• Higher Order Functions -> Command Pattern

• Fold -> Visitor pattern

Page 6: F# Server-side programming

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

C# ObjectPool

Page 8: F# Server-side programming

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

F# - Fracture IO

Open source high performance Socket, Pipeline, and agent library

Page 10: F# Server-side programming

Sockets

2 Models of Operation

• AsyncResult Model

• SocketAsyncEventArgs Model

Page 11: F# Server-side programming

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

F# AsyncResult

Page 13: F# Server-side programming

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

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

CPU & Threads

SocketAsyncEventArgs IAsyncResult

Page 16: F# Server-side programming

MemorySocketAsyncEventArgs IAsyncResult

Page 17: F# Server-side programming

Garbage collectionSocketAsyncEventArgs IAsyncResult

Page 18: F# Server-side programming

Fracture Socket Implementation

Page 19: F# Server-side programming

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

Introducing Fracture-IO

• High performance Socket library

• Highly compositional pipeline library

Page 21: F# Server-side programming

Pipelines

• Closed Pipelines– Tomas Petricek• Image Processing Pipeline

• Open Pipelines– Pipelets

Page 22: F# Server-side programming

Closed Pipelines

Page 23: F# Server-side programming

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

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

Pipelets Implementation

Page 26: F# Server-side programming

Pipelets in use

Page 27: F# Server-side programming

Future Directions

• Distributed Pipelets– Wave Pipelines

– Synchronous buffered Pipeline

• Advanced agent based programming- Supervision

- Pooling

- Control Messages