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?
Thanks!
module Program
open System
open System.Diagnostics
[<AutoOpen>]
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 <> 'q'
let rec addOne x stop =
let r = x + 1
if stop() then r
else addOne r stop
let finished stopticks = (fun _ -> Stopwatch.GetTimestamp() >= 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 |> TimeSpan).TotalSeconds
let pretty = prettyNumbers result
sprintf "performed %s operations in %f seconds" pretty final |> Console.WriteLine
let op duration start =
duration
|> secondsToTicks
|> (+) start
|> finished
|> addOne 0
let opAsync duration start procs =
[ for i in [ 1..procs ] -> async { return op duration start } ]
|> Async.Parallel
|> Async.RunSynchronously
[<EntryPoint>]
let main argv =
let loop() =
let input =
match Int32.TryParse(pickRunmode()) with
| true, i -> i
| _ -> 1
input
|> string
|> feedback
|> ignore
let start = Stopwatch.GetTimestamp()
let result = opAsync 1L start input |> Seq.sum
printResult result start |> ignore
quitOrContinue()
while loop() do
()
0