Compare performance of simple addition on one to many cores I read recently that ENIAC originally was capable of 5000 additions per second.  Naturally, I had to test my own laptop's capabilities and this became an instructive experiment in F#, which I suck at.

So, I am looking for feedback in two areas:


What is the most concise way to write this in F#, or at least most closely aligned with the functional paradigm?
Did I miss something for performance? Can this be done in a much more performant fashion?




module Program

open System
open System.Diagnostics

[&lt;AutoOpen&gt;]
module timingStuff = 
    let pickRunmode() = 
        Console.WriteLine("choose number of processes to spawn (default 1)")
        Console.ReadLine()

    let feedback (input : string) = 
        Console.WriteLine("you picked {0}", input)
        Console.WriteLine("now running")

    let quitOrContinue() = 
        Console.WriteLine("q to quit else continue with keypress")
        Console.ReadKey().KeyChar &lt;&gt; 'q'

    let rec addOne x stop = 
        let r = x + 1
        if stop() then r
        else addOne r stop

    let finished stopticks = (fun _ -&gt; Stopwatch.GetTimestamp() &gt;= stopticks)
    let secondsToTicks x = x * 1000L * 10000L
    let prettyNumbers (x : int) = String.Format("{0:#,0}", x)

    let printResult result start = 
        let final = (Stopwatch.GetTimestamp() - start |&gt; TimeSpan).TotalSeconds
        let pretty = prettyNumbers result
        sprintf "performed %s operations in %f seconds" pretty final |&gt; Console.WriteLine

    let op duration start = 
        duration
        |&gt; secondsToTicks
        |&gt; (+) start
        |&gt; finished
        |&gt; addOne 0

    let opAsync duration start procs = 
        [ for i in [ 1..procs ] -&gt; async { return op duration start } ]
        |&gt; Async.Parallel
        |&gt; Async.RunSynchronously

[&lt;EntryPoint&gt;]
let main argv = 
    let loop() = 
        let input = 
            match Int32.TryParse(pickRunmode()) with
            | true, i -&gt; i
            | _ -&gt; 1
        input
        |&gt; string
        |&gt; feedback
        |&gt; ignore
        let start = Stopwatch.GetTimestamp()
        let result = opAsync 1L start input |&gt; Seq.sum
        printResult result start |&gt; ignore
        quitOrContinue()
    while loop() do
        ()
    0
So for my skill level there are some minor recommendations.
So for me Feedback would be a little bit more readable in this form:

let feedback input = 
    [   sprintf "you picked %s" input
        "now running" ] |&gt; List.iter Console.WriteLine


There are some brackets that can be reduced, so simple write. 

Console.WriteLine "q to quit else continue with keypress"


And finally there is no need to ignore unit, since ignore is a code smell and you actually don not need them so just ignore them.

And that is what I changed it to:

module Program

open System
open System.Diagnostics

[&lt;AutoOpen&gt;]
module timingStuff = 
    // no side effects
    let secondsToTicks = (*) (1000L * 10000L)

    let prettyNumbers (x:int) = String.Format("{0:#,0}", x)

    // no side effects if stop has side effect (but here it has)
    let rec addOne x stop = 
        let r = x + 1
        if stop() then r
        else addOne r stop

    // with side effects    
    let pickRunmode() = 
        "choose number of processes to spawn (default 1)" |&gt; Console.WriteLine
        Console.ReadLine()

    let feedback input = 
        [   sprintf "you picked %s" input
            "now running" ] |&gt; List.iter Console.WriteLine 

    let quitOrContinue() = 
        Console.WriteLine "q to quit else continue with keypress"
        Console.ReadKey().KeyChar &lt;&gt; 'q'


    let finished stopticks = fun _ -&gt; Stopwatch.GetTimestamp() &gt;= stopticks

    let printResult result start = 
        let final = (Stopwatch.GetTimestamp() - start |&gt; TimeSpan).TotalSeconds
        let pretty = prettyNumbers result
        sprintf "performed %s operations in %f seconds" pretty final |&gt; Console.WriteLine

    let op duration start = 
        duration
        |&gt; secondsToTicks
        |&gt; (+) start
        |&gt; finished
        |&gt; addOne 0

    let opAsync duration start procs = 
        [ for i in [ 1..procs ] -&gt; async { return op duration start } ]
        |&gt; Async.Parallel
        |&gt; Async.RunSynchronously

[&lt;EntryPoint&gt;]
let main argv = 
    let loop _ = 
        let input = 
            match Int32.TryParse(pickRunmode()) with
            | true, i -&gt; i
            | _ -&gt; 1
        input |&gt; string |&gt; feedback
        let start = Stopwatch.GetTimestamp()
        let result = 
            opAsync 1L start input 
            |&gt; Seq.sum
        printResult result start 

        quitOrContinue() 

    while loop() do ()
    0