module Set = open System.Threading.Tasks [] let private SUB_SET_SIZE = 150 let ofSortedSeq (sortedItems:seq<_>) = let whenAll a b f = let waitingTask = Task.WhenAll [|a; b|] waitingTask.ContinueWith (fun _ -> f ()) let rec partialUnion = function | [_:Task<_>] :: _ as original -> original | [[a;b]] -> [] :: [whenAll a b (fun () -> Set.union a.Result b.Result)] :: [] | [a;b]::[]::tl -> [] :: [whenAll a b (fun () -> Set.union a.Result b.Result)] :: tl | [a;b]::[c]::tl -> [] :: (partialUnion ([whenAll a b (fun () -> Set.union a.Result b.Result); c] :: tl)) | _ -> failwith "Unexpected state" let rec combinePartialUnion (combined:Task<_>) = function | [] -> combined.Result | [] :: tl -> combinePartialUnion combined tl | (a:Task<_> :: tl1) :: tl2 -> combinePartialUnion (whenAll combined a (fun () -> Set.union combined.Result a.Result)) (tl1 :: tl2) let enumerator = sortedItems.GetEnumerator () let rec addNext current counter results = let next = enumerator.Current :: current let createSubSet () = Task.Run (fun () -> Set.ofSeq next) match enumerator.MoveNext (), results with | false, _ -> combinePartialUnion (createSubSet ()) results | true, _ when counter < SUB_SET_SIZE -> addNext next (counter+1) results | true, []::tl -> addNext [] 0 ([createSubSet ()]::tl) | true, [a]::tl -> addNext [] 0 (partialUnion ([a;createSubSet ()]::tl)) | _ -> failwith "Unexpected state" if enumerator.MoveNext () then addNext [] 0 ([[]]) else Set.empty let ofSeqViaSort (items:seq<_>) = items |> Seq.sort |> fun sorted -> ofSortedSeq sorted module Newtonsoft = open System.Reflection open Newtonsoft.Json type private fastFSharpSetHelper<'f when 'f : comparison>() = static member readJson (reader:JsonReader, serializer:JsonSerializer) = serializer.Deserialize> (reader) |> Set.ofSortedSeq let fastFSharpSetConverter = { new JsonConverter() with override __.CanConvert t = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof> override __.CanWrite = false override __.WriteJson (_, _, _) = raise <| System.NotImplementedException "CanWrite = false" override __.ReadJson (reader, t, _, serializer) = typedefof>.MakeGenericType (t.GetGenericArguments()) |> fun converter -> converter.GetMethod ("readJson", BindingFlags.Static ||| BindingFlags.NonPublic) |> fun readJson -> readJson.Invoke (null, [| reader; serializer |]) }