Example this code:
let b id =
async {
printfn "running %A \n" id
System.Threading.Thread.Sleep(2000)
printfn "finish %A \n" id
}
let works = [1..100]
works |> Seq.map b|> Async.Parallel |> Async.RunSynchronously
how many threads will be used ?
The answer is; we can't know. And why would we want to?
Also, it's not clear what you're asking. Are you asking whether b will be run on a single thread from start to end? For this example the answer is yes, but a slight change could turn the answer into a no. Are you asking how many threads will be used in total? By ID or by runs? How many will run simultaneously?
It is often better just to think in terms of asyncs rather than threads, since threads are just resources used behind the scenes by asyncs.
Some more info.
There will be a thread pool that is used to run the asyncs, and the size of that thread pool is usually the number of processors. On my machine, I have 8 processors with hyperthreading, so then I guess there will be 16 threads in the thread pool.
The code in the Q produces a quite messy output, since printfn does not write atomically to the console. In order to see line by line output, I will use Console.WriteLine, which will write lines atomically.
open System
let t: bool[] = Array.zeroCreate 10000
let b id =
async {
let threadId = Threading.Thread.CurrentThread.ManagedThreadId
t.[threadId] <- true
Console.WriteLine $#"running {id} on {threadId}"
Threading.Thread.Sleep 2000
Console.WriteLine $#"finish {id} on {threadId}"
}
[<EntryPoint>]
let main argv =
Console.WriteLine "Start"
[1..100]
|> Seq.map b
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
Console.WriteLine "Done"
let n = t |> Array.filter id |> Array.length
Console.WriteLine $#"n = {n}"
Console.ReadKey() |> ignore
0
So here we keep track of which threads are used overall.
It turns out that the number of threads used varies from 19 to 23 on my machine, and I bet it can be lower and higher. But why isn't the number 16 on my machine? I suspect the reason for this higher than expected number is that the asyncs use Threading.Thread.Sleep instead of Async.Sleep. When a thread from the thread pool turns out to be long running, then soon a new thread must be allocated in its stead so that the corresponding processor can still be used effectively by the thread pool. If the length of the sleep is increased, then the number of threads used overall go up. If I try with Threading.Thread.Sleep 100_000, then 100 threads are used.
In production, use Async.Sleep instead for actually sleeping an async for a while, so that thread pool threads are not blocked, but returned to the thread pool so that they can do other work instead of just doing a blocked sleep for a long time. When I do that here, only 33 threads are used. But 33 still seems high. Do I still have a problem? I don't think so. Let's explore some more to see why.
There is an overload of Async.Parallel which can be used to specify the degree of parallelism. Let's see what happens.
open System
let t: bool[] = Array.zeroCreate 10000
let b id =
async {
let threadId = Threading.Thread.CurrentThread.ManagedThreadId
t.[threadId] <- true
Console.WriteLine $#"running {id} on {threadId}"
// Threading.Thread.Sleep(2000)
do! Async.Sleep 2000
let threadId2 = Threading.Thread.CurrentThread.ManagedThreadId
t.[threadId2] <- true
Console.WriteLine $#"finish {id} on {threadId2}"
if threadId <> threadId2 then Console.WriteLine "NOT THE SAME THREAD!"
}
let asyncParallel x y = Async.Parallel (y, x)
[<EntryPoint>]
let main argv =
Console.WriteLine "Start"
[1..100]
|> Seq.map b
|> asyncParallel 3
|> Async.RunSynchronously
|> ignore
Console.WriteLine "Done"
let n = t |> Array.filter id |> Array.length
Console.WriteLine $#"n = {n}"
Console.ReadKey() |> ignore
0
When I run this, I usually get n = 6, but I've also gotten 5. Why does it tend towards 6, but not always be exactly 6? And why isn't it 3?
If the nasty Threading.Thread.Sleep is used instead of Async.Sleep, then n will tend towards 3.
If one more Async.Sleep is inserted into b, so that there are two, will then n tend towards 9? Surprisingly, no! It's still at 6.
So far it looks like use of one or more bang - the do! in our case - will cause use of two threads per b running in total, instead of only one. Not sure why, but of course it doesn't mean two threads are used simultaneously by one run of b, but rather in sequence, before and after the Async.Sleep. (Can also sometimes happen to be the same thread that continues the work, which can explain why I got 5 rather than 6 one time.)
Now we can guess more easily as to why 33 threads was used when Threading.Thread.Sleep 100_000 was replaced with Async.Sleep 100_000. It's just one more than 32, which is 2 * 16, and 16 is the expected number of threads in the thread pool. When Async.Sleep 500_000 is used, the number of threads involved is still only 33 on my machine.
We haven't really reached any conclusions with the experiments, but we've gotten some insight into how things work.
Related
In the following code, both do! ag.AsyncAdd (Some i) or ag.AsyncAdd (Some i) (in the function enqueue()) work. What's the difference between them? It seems do! ... will make enqueuing and dequeuing calls more mixed? How?
open FSharpx.Control
let test () =
let ag = new BlockingQueueAgent<int option>(500)
let enqueue() = async {
for i = 1 to 15 do
// ag.AsyncAdd (Some i) // works too
do! ag.AsyncAdd (Some i)
printfn "=> %d" i }
async {
do! [ for i = 1 to 10 do yield enqueue() ]
|> Async.Parallel |> Async.Ignore
for i = 1 to 5 do ag.Add None
} |> Async.Start
let rec dequeue() =
async {
let! m = ag.AsyncGet()
match m with
| Some v ->
printfn "<= %d" v
return! dequeue()
| None ->
printfn "Done"
}
[ for i = 1 to 5 do yield dequeue() ]
|> Async.Parallel |> Async.Ignore |> Async.RunSynchronously
0
Inside any F# computation expression, any keyword that ends with ! tends to mean "Handle this one specially, according to the rules of this block". E.g., in an async { } block, the let! keyword means "await the result, then assign the result to this variable" and the do! keyword means "await this asynchronous operation, but throw away the result and don't assign it to anything". If you don't use a do! keyword, then you are not awaiting the result of that operation.
So with a do! keyword inside your enqueue function, you are doing the following fifteen times:
Kick off an AsyncAdd operation
Wait for it to complete
print "=> 1" (or 2, or 3...)
Without a do! keyword, you are doing the following:
Kick off fifteen AsyncAdd operations as fast as possible
After kicking each one off, print "=> 1" (or 2, or 3...)
It sounds like you don't yet fully understand how F#'s computation expressions work behind the scenes. I recommend reading Scott Wlaschin's excellent site to gain more understanding: first https://fsharpforfunandprofit.com/posts/concurrency-async-and-parallel/ and then https://fsharpforfunandprofit.com/series/computation-expressions.html so that when you read the second series of articles, you're building on a bit of existing knowledge.
From FSharpx source code (see comments):
/// Asynchronously adds item to the queue. The operation ends when
/// there is a place for the item. If the queue is full, the operation
/// will block until some items are removed.
member x.AsyncAdd(v:'T, ?timeout) =
agent.PostAndAsyncReply((fun ch -> AsyncAdd(v, ch)), ?timeout=timeout)
When you do not use do!, you do not block enqueue thread in case if queue is full (500 items in queue as you state in constructor). So, when you changed loops to higher number, you spammed MailboxProcessor queue with messages (behind the scene FSharpx uses MailboxProcessor - check docs for this class) of type AsyncAdd from all iterations of all enqueue thread. This slows down another operation, agent.Scan:
and fullQueue() =
agent.Scan(fun msg ->
match msg with
| AsyncGet(reply) -> Some(dequeueAndContinue(reply))
| _ -> None )
because you have in queue a lot of AsyncAdd and AsyncGet.
In case, when you put do! before AsyncAdd, you enqueue threads will be blocked at moment when there are 500 items in queue and no additional messages would be generated for MailboxProcessor, thus agent.Scan will work fast. When dequeue thread takes an item and the number of them becomes 499, new enqueue thread awaiks and adds new item and then goes to next iteration of a loop, put new AsyncAdd message into MailboxProcessor and again, goes to sleep till moment of dequeue. Thus, MailboxProcessor is not spammed with messages AsyncAdd of all iterations of one enqueue thread. Note: queue of items and queue of MailboxProcessor messages are different queues.
I have a simple TCP server that listens to connection client and it looks quite simple
let Listener (ip:IPAddress) (port:int32) =
async {
let listener = TcpListener(ip, port)
listener.Start()
_logger.Info(sprintf "Server binded to IP: %A - Port: %i" ip port)
let rec listenerPending (listener : TcpListener) =
async {
if not (listener.Pending()) then return! listenerPending listener // MEMMORY LEAK SOURCE
printfn "Test"
}
listenerPending listener |> Async.Start
}
Well, it looks simple, but I have a memory leak problem: when it is waiting for a connection, it eats RAM like candy.
I suppose it is connected with recursive function but have no idea what to do to stabilize it.
The problem is that your listenerPending function is not tail-recursive. This is a bit counter-intuitive - but the return! keyword is not like imperative "return" that breaks the current execution, but rather a call to some other function that can be tail-recursive (as opposed to do! which never is) if it is in the right location.
To illustrate, consider the following:
let rec demo n =
async {
if n > 0 then return! demo (n-1)
printfn "%d" n
}
demo 10 |> Async.RunSynchronously
This actually prints numbers from 0 to 10! This is because the code after return! will still get executed after the recursive call finishes. The structure of your code is similar, except that your loop never terminates (at least not quickly enough). You can fix that just by removing the code after return! (or perhaps moving it to an else branch).
Also, it's worth noting that your code is not really asynchronous - you don't have any non-blocking waiting in it. You should probably be doing something like this instead of a loop:
let! socket = listener.AcceptSocketAsync () |> Async.AwaitTask
What is the proper way to extend the available operators when using RX?
I'd like to build out some operations that I think would be useful.
The first operation is simply the standard deviation of a series.
The second operation is the nth lagged value i.e. if we are lagging 2 and our series is A B C D E F when F is pushed the lag would be D when A is pushed the lag would be null/empty when B is pushed the lag would be null/empty when C is pushed the Lag would be A
Would it make sense to base these types of operators off of the built-ins from rx.codeplex.com or is there an easier way?
In idiomatic Rx, arbitrary delays can be composed by Zip.
let lag (count : int) o =
let someo = Observable.map Some o
let delayed = Observable.Repeat(None, count).Concat(someo)
Observable.Zip(someo, delayed, (fun c d -> d))
As for a rolling buffer, the most efficient way is to simply use a Queue/ResizeArray of fixed size.
let rollingBuffer (size : int) o =
Observable.Create(fun (observer : IObserver<_>) ->
let buffer = new Queue<_>(size)
o |> Observable.subscribe(fun v ->
buffer.Enqueue(v)
if buffer.Count = size then
observer.OnNext(buffer.ToArray())
buffer.Dequeue() |> ignore
)
)
For numbers |> rollingBuffer 3 |> log:
seq [0L; 1L; 2L]
seq [1L; 2L; 3L]
seq [2L; 3L; 4L]
seq [3L; 4L; 5L]
...
For pairing adjacent values, you can just use Observable.pairwise
let delta (a, b) = b - a
let deltaStream = numbers |> Observable.pairwise |> Observable.map(delta)
Observable.Scan is more concise if you want to apply a rolling calculation .
Some of these are easier than others (as usual). For a 'lag' by count (rather than time) you just create a sliding window by using Observable.Buffer equivalent to the size of 'lag', then take the first element of the result list.
So far lag = 3, the function is:
obs.Buffer(3,1).Select(l => l.[0])
This is pretty straightforward to turn into an extension function. I don't know if it is efficient in that it reuses the same list, but in most cases that shouldn't matter. I know you want F#, the translation is straightforward.
For running aggregates, you can usually use Observable.Scan to get a 'running' value. This is calculated based on all values seen so far (and is pretty straightforward to implement) - ie all you have to implement each subsequent element is the previous aggregate and the new element.
If for whatever reason you need a running aggregate based on a sliding window, then we get into more difficult domain. Here you first need an operation that can give you a sliding window - this is covered by Buffer above. However, then you need to know which values have been removed from this window, and which have been added.
As such, I recommend a new Observable function that maintains an internal window based on existing window + new value, and returns new window + removed value + added value. You can write this using Observable.Scan (I recommend an internal Queue for efficient implementation). It should take a function for determining which values to remove given a new value (this way it can be parameterised for sliding by time or by count).
At that point, Observable.Scan can again be used to take the old aggregate + window + removed values + added value and give a new aggregate.
Hope this helps, I do realise it's a lot of words. If you can confirm the requirement, I can help out with the actual extension method for that specific use case.
For lag, you could do something like
module Observable =
let lag n obs =
let buf = System.Collections.Generic.Queue()
obs |> Observable.map (fun x ->
buf.Enqueue(x)
if buf.Count > n then Some(buf.Dequeue())
else None)
This:
Observable.Range(1, 9)
|> Observable.lag 2
|> Observable.subscribe (printfn "%A")
|> ignore
prints:
<null>
<null>
Some 1
Some 2
Some 3
Some 4
Some 5
Some 6
Some 7
Lazy evaluation is a great boon for stuff like processing huge files that will not fit in main memory at one go. However, suppose there are some elements in the sequence that I want evaluated immediately, while the rest can be lazily computed - is there any way to specify that?
Specific problem: (in case that helps to answer the question)
Specifically, I am using a series of IEnumerables as iterators for multiple sequences - these sequences are data read from files opened using BinaryReader streams (each sequence is responsible for the reading in of data from one of the files). The MoveNext() on these is to be called in a specific order. Eg. iter0 then iter1 then iter5 then iter3 .... and so on. This order is specified in another sequence index = {0,1,5,3,....}. However sequences being lazy, the evaluation is naturally done only when required. Hence, the file reads (for the sequences right at the beginning that read from files on disk) happens as the IEnumerables for a sequence are moving. This is causing an illegal file access - a file that is being read by one process is accessed again (as per the error msg).
True, the illegal file access could be for other reasons, and after having tried my best to debug other causes a partially lazy evaluation might be worth trying out.
While I agree with Tomas' comment: you shouldn't need this if file sharing is handled properly, here's one way to eagerly evaluate the first N elements:
let cacheFirst n (items: seq<_>) =
seq {
use e = items.GetEnumerator()
let i = ref 0
yield!
[
while !i < n && e.MoveNext() do
yield e.Current
incr i
]
while e.MoveNext() do
yield e.Current
}
Example
let items = Seq.initInfinite (fun i -> printfn "%d" i; i)
items
|> Seq.take 10
|> cacheFirst 5
|> Seq.take 3
|> Seq.toList
Output
0
1
2
3
4
val it : int list = [0; 1; 2]
Daniel's solution is sound, but I don't think we need another operator, just Seq.cache for most cases.
First cache your sequence:
let items = Seq.initInfinite (fun i -> printfn "%d" i; i) |> Seq.cache
Eager evaluation followed by lazy access from the beginning:
let eager = items |> Seq.take 5 |> Seq.toList
let cached = items |> Seq.take 3 |> Seq.toList
This will evaluate the first 5 elements once (during eager) but make them cached for secondary access.
Just naively using Seq.length may be not good enough as will blow up on infinite sequences.
Getting more fancy with using something like ss |> Seq.truncate n |> Seq.length will work, but behind the scene would involve double traversing of the argument sequence chunk by IEnumerator's MoveNext().
The best approach I was able to come up with so far is:
let hasAtLeast n (ss: seq<_>) =
let mutable result = true
use e = ss.GetEnumerator()
for _ in 1 .. n do result <- e.MoveNext()
result
This involves only single sequence traverse (more accurately, performing e.MoveNext() n times) and correctly handles boundary cases of empty and infinite sequences. I can further throw in few small improvements like explicit processing of specific cases for lists, arrays, and ICollections, or some cutting on traverse length, but wonder if any more effective approach to the problem exists that I may be missing?
Thank you for your help.
EDIT: Having on hand 5 overall implementation variants of hasAtLeast function (2 my own, 2 suggested by Daniel and one suggested by Ankur) I've arranged a marathon between these. Results that are tie for all implementations prove that Guvante is right: a simplest composition of existing algorithms would be the best, there is no point here in overengineering.
Further throwing in the readability factor I'd use either my own pure F#-based
let hasAtLeast n (ss: seq<_>) =
Seq.length (Seq.truncate n ss) >= n
or suggested by Ankur the fully equivalent Linq-based one that capitalizes on .NET integration
let hasAtLeast n (ss: seq<_>) =
ss.Take(n).Count() >= n
Here's a short, functional solution:
let hasAtLeast n items =
items
|> Seq.mapi (fun i x -> (i + 1), x)
|> Seq.exists (fun (i, _) -> i = n)
Example:
let items = Seq.initInfinite id
items |> hasAtLeast 10000
And here's an optimally efficient one:
let hasAtLeast n (items:seq<_>) =
use e = items.GetEnumerator()
let rec loop n =
if n = 0 then true
elif e.MoveNext() then loop (n - 1)
else false
loop n
Functional programming breaks up work loads into small chunks that do very generic tasks that do one simple thing. Determining if there are at least n items in a sequence is not a simple task.
You already found both the solutions to this "problem", composition of existing algorithms, which works for the majority of cases, and creating your own algorithm to solve the issue.
However I have to wonder whether your first solution wouldn't work. MoveNext() is only called n times on the original method for certain, Current is never called, and even if MoveNext() is called on some wrapper class the performance implications are likely tiny unless n is huge.
EDIT:
I was curious so I wrote a simple program to test out the timing of the two methods. The truncate method was quicker for a simple infinite sequence and one that had Sleep(1). It looks like I was right when your correction sounded like overengineering.
I think clarification is needed to explain what is happening in those methods. Seq.truncate takes a sequence and returns a sequence. Other than saving the value of n it doesn't do anything until enumeration. During enumeration it counts and stops after n values. Seq.length takes an enumeration and counts, returning the count when it ends. So the enumeration is only enumerated once, and the amount of overhead is a couple of method calls and two counters.
Using Linq this would be as simple as:
let hasAtLeast n (ss: seq<_>) =
ss.Take(n).Count() >= n
Seq take method blows up if there are not enough elements.
Example usage to show it traverse seq only once and till required elements:
seq { for i = 0 to 5 do
printfn "Generating %d" i
yield i }
|> hasAtLeast 4 |> printfn "%A"