Adding more F# .fs samples. Fixes #1814

This commit is contained in:
Arfon Smith
2014-12-03 08:36:58 -06:00
parent d06529fd14
commit 70e0ce1d73
6 changed files with 769 additions and 0 deletions

65
samples/F#/JsonFormat.fs Normal file
View File

@@ -0,0 +1,65 @@
namespace Nessos.FsPickler.Json
open System
open System.IO
open System.Text
open Newtonsoft.Json
open Nessos.FsPickler
/// <summary>
/// Factory methods for the Json serialization format.
/// </summary>
type JsonPickleFormatProvider internal (indent, omitHeader) as self =
let isCustomSeq isTopLevelSequence =
isTopLevelSequence && self.OmitHeader && self.UseCustomTopLevelSequenceSeparator
let mutable sequenceSeparator = " "
member val Indent = indent with get,set
member val OmitHeader = omitHeader with get,set
member val UseCustomTopLevelSequenceSeparator = false with get,set
member __.SequenceSeparator
with get () = sequenceSeparator
and set sep =
if sep <> null && String.IsNullOrWhiteSpace sep then
sequenceSeparator <- sep
else
invalidArg "SequenceSeparator" "should be non-null whitespace."
interface ITextPickleFormatProvider with
member __.Name = "Json"
// see discussion : https://github.com/nessos/FsPickler/issues/17
member __.DefaultEncoding = new UTF8Encoding(false) :> Encoding
member __.CreateWriter (stream, encoding, isTopLevelSequence, leaveOpen) =
#if NET40
if leaveOpen then raise <| new NotSupportedException("'leaveOpen' not supported in .NET 40.")
let sw = new StreamWriter(stream, encoding)
#else
let sw = new StreamWriter(stream, encoding, 1024, leaveOpen)
#endif
let jw = new JsonTextWriter(sw)
new JsonPickleWriter(jw, __.OmitHeader, __.Indent, isCustomSeq isTopLevelSequence, sequenceSeparator, leaveOpen) :> _
member __.CreateReader (stream, encoding, isTopLevelSequence, leaveOpen) =
#if NET40
if leaveOpen then raise <| new NotSupportedException("'leaveOpen' not supported in .NET 40.")
let sr = new StreamReader(stream, encoding)
#else
let sr = new StreamReader(stream, encoding, true, 1024, leaveOpen)
#endif
let jr = new JsonTextReader(sr)
new JsonPickleReader(jr, __.OmitHeader, isCustomSeq isTopLevelSequence, leaveOpen) :> _
member __.CreateWriter (textWriter, isTopLevelSequence, leaveOpen) =
let jw = new JsonTextWriter(textWriter)
new JsonPickleWriter(jw, __.OmitHeader, __.Indent, isCustomSeq isTopLevelSequence, sequenceSeparator, leaveOpen) :> _
member __.CreateReader (textReader, isTopLevelSequence, leaveOpen) =
let jr = new JsonTextReader(textReader)
new JsonPickleReader(jr, __.OmitHeader, isCustomSeq isTopLevelSequence, leaveOpen) :> _

202
samples/F#/JsonReader.fs Normal file
View File

@@ -0,0 +1,202 @@
namespace Nessos.FsPickler.Json
open System
open System.Collections.Generic
open System.Globalization
open System.IO
open System.Numerics
open System.Text
open Newtonsoft.Json
open Nessos.FsPickler
/// <summary>
/// Json format deserializer
/// </summary>
type internal JsonPickleReader (jsonReader : JsonReader, omitHeader, isTopLevelSequence, leaveOpen) =
do
jsonReader.CloseInput <- not leaveOpen
jsonReader.SupportMultipleContent <- isTopLevelSequence
let isBsonReader = match jsonReader with :? Bson.BsonReader -> true | _ -> false
let mutable depth = 0
let arrayStack = new Stack<int> ()
do arrayStack.Push Int32.MinValue
// do not write tag if omitting header or array element
let omitTag () = (omitHeader && depth = 0) || arrayStack.Peek() = depth - 1
interface IPickleFormatReader with
member __.BeginReadRoot (tag : string) =
do jsonReader.Read() |> ignore
if omitHeader then () else
if jsonReader.TokenType <> JsonToken.StartObject then raise <| new FormatException("invalid json root object.")
else
do jsonReader.MoveNext()
let version = jsonReader.ReadPrimitiveAs<string> false "FsPickler"
if version <> jsonFormatVersion then
let v = Version(version)
raise <| new FormatException(sprintf "Invalid FsPickler format version %O." version)
let sTag = jsonReader.ReadPrimitiveAs<string> false "type"
if tag <> sTag then
raise <| new InvalidPickleTypeException(tag, sTag)
member __.EndReadRoot () =
if not omitHeader then jsonReader.Read() |> ignore
member __.BeginReadObject (tag : string) =
if not <| omitTag () then
jsonReader.ReadProperty tag
jsonReader.MoveNext ()
if isTopLevelSequence && depth = 0 then
arrayStack.Push depth
depth <- depth + 1
ObjectFlags.IsSequenceHeader
else
match jsonReader.TokenType with
| JsonToken.Null -> ObjectFlags.IsNull
| JsonToken.StartArray ->
jsonReader.MoveNext()
arrayStack.Push depth
depth <- depth + 1
ObjectFlags.IsSequenceHeader
| JsonToken.StartObject ->
do jsonReader.MoveNext()
depth <- depth + 1
if jsonReader.ValueAs<string> () = "_flags" then
jsonReader.MoveNext()
let csvFlags = jsonReader.ValueAs<string>()
jsonReader.MoveNext()
parseFlagCsv csvFlags
else
ObjectFlags.None
| token -> raise <| new FormatException(sprintf "expected start of Json object but was '%O'." token)
member __.EndReadObject () =
if isTopLevelSequence && depth = 1 then
arrayStack.Pop () |> ignore
depth <- depth - 1
jsonReader.Read() |> ignore
else
match jsonReader.TokenType with
| JsonToken.Null -> ()
| JsonToken.EndObject -> depth <- depth - 1
| JsonToken.EndArray ->
arrayStack.Pop() |> ignore
depth <- depth - 1
| token -> raise <| new FormatException(sprintf "expected end of Json object but was '%O'." token)
if omitHeader && depth = 0 then ()
else jsonReader.Read() |> ignore
member __.SerializeUnionCaseNames = true
member __.PreferLengthPrefixInSequences = false
member __.ReadNextSequenceElement () =
if isTopLevelSequence && depth = 1 then
jsonReader.TokenType <> JsonToken.None
else
jsonReader.TokenType <> JsonToken.EndArray
member __.ReadCachedObjectId () = jsonReader.ReadPrimitiveAs<int64> false "id"
member __.ReadBoolean tag = jsonReader.ReadPrimitiveAs<bool> (omitTag ()) tag
member __.ReadByte tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag |> byte
member __.ReadSByte tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag |> sbyte
member __.ReadInt16 tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag |> int16
member __.ReadInt32 tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag |> int
member __.ReadInt64 tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag
member __.ReadUInt16 tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag |> uint16
member __.ReadUInt32 tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag |> uint32
member __.ReadUInt64 tag = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag |> uint64
member __.ReadSingle tag =
if not <| omitTag () then
jsonReader.ReadProperty tag
jsonReader.MoveNext()
let value =
match jsonReader.TokenType with
| JsonToken.Float -> jsonReader.ValueAs<double> () |> single
| JsonToken.String -> Single.Parse(jsonReader.ValueAs<string>(), CultureInfo.InvariantCulture)
| _ -> raise <| new FormatException("not a float.")
jsonReader.Read() |> ignore
value
member __.ReadDouble tag =
if not <| omitTag () then
jsonReader.ReadProperty tag
jsonReader.MoveNext()
let value =
match jsonReader.TokenType with
| JsonToken.Float -> jsonReader.ValueAs<double> ()
| JsonToken.String -> Double.Parse(jsonReader.ValueAs<string>(), CultureInfo.InvariantCulture)
| _ -> raise <| new FormatException("not a float.")
jsonReader.Read() |> ignore
value
member __.ReadChar tag = let value = jsonReader.ReadPrimitiveAs<string> (omitTag ()) tag in value.[0]
member __.ReadString tag = jsonReader.ReadPrimitiveAs<string> (omitTag ()) tag
member __.ReadBigInteger tag = jsonReader.ReadPrimitiveAs<string> (omitTag ()) tag |> BigInteger.Parse
member __.ReadGuid tag =
if isBsonReader then
jsonReader.ReadPrimitiveAs<Guid> (omitTag ()) tag
else
jsonReader.ReadPrimitiveAs<string> (omitTag ()) tag |> Guid.Parse
member __.ReadTimeSpan tag = jsonReader.ReadPrimitiveAs<string> (omitTag ()) tag |> TimeSpan.Parse
member __.ReadDecimal tag = jsonReader.ReadPrimitiveAs<string> (omitTag ()) tag |> decimal
// BSON spec mandates the use of Unix time;
// this has millisecond precision which results in loss of accuracy w.r.t. ticks
// since the goal of FsPickler is to offer faithful representations of .NET objects
// we choose to override the spec and serialize ticks outright.
// see also https://json.codeplex.com/discussions/212067
member __.ReadDate tag =
if isBsonReader then
let ticks = jsonReader.ReadPrimitiveAs<int64> (omitTag ()) tag
DateTime(ticks)
else
jsonReader.ReadPrimitiveAs<DateTime> (omitTag ()) tag
member __.ReadBytes tag =
if not <| omitTag () then
jsonReader.ReadProperty tag
jsonReader.Read() |> ignore
let bytes =
if jsonReader.TokenType = JsonToken.Null then null
elif isBsonReader then jsonReader.ValueAs<byte []> ()
else
let base64 = jsonReader.ValueAs<string> ()
Convert.FromBase64String base64
jsonReader.Read() |> ignore
bytes
member __.IsPrimitiveArraySerializationSupported = false
member __.ReadPrimitiveArray _ _ = raise <| new NotImplementedException()
member __.Dispose () = (jsonReader :> IDisposable).Dispose()

View File

@@ -0,0 +1,85 @@
namespace Nessos.FsPickler.Json
open System
open Nessos.FsPickler
type internal OAttribute = System.Runtime.InteropServices.OptionalAttribute
type internal DAttribute = System.Runtime.InteropServices.DefaultParameterValueAttribute
/// <summary>
/// Json pickler instance.
/// </summary>
type JsonSerializer =
inherit FsPicklerTextSerializer
val private format : JsonPickleFormatProvider
/// <summary>
/// Initializes a new Json pickler instance.
/// </summary>
/// <param name="indent">indent out Json pickles.</param>
/// <param name="omitHeader">omit FsPickler header in Json pickles.</param>
/// <param name="typeConverter">specify a custom type name converter.</param>
new ([<O;D(null)>] ?indent, [<O;D(null)>] ?omitHeader, [<O;D(null)>] ?typeConverter) =
let indent = defaultArg indent false
let omitHeader = defaultArg omitHeader false
let json = new JsonPickleFormatProvider(indent, omitHeader)
{
inherit FsPicklerTextSerializer(json, ?typeConverter = typeConverter)
format = json
}
/// <summary>
/// Gets or sets whether Json output should be indented.
/// </summary>
member x.Indent
with get () = x.format.Indent
and set b = x.format.Indent <- b
/// <summary>
/// Gets or sets whether FsPickler headers should be ignored in pickle format.
/// </summary>
member x.OmitHeader
with get () = x.format.OmitHeader
and set b = x.format.OmitHeader <- b
/// <summary>
/// Gets or sets a non-null whitespace string that serves as a custom, top-level sequence separator.
/// </summary>
member x.SequenceSeparator
with get () = x.format.SequenceSeparator
and set sep = x.format.SequenceSeparator <- sep
/// <summary>
/// Gets or sets whether top-level sequences should be serialized using the custom separator.
/// </summary>
member x.UseCustomTopLevelSequenceSeparator
with get () = x.format.UseCustomTopLevelSequenceSeparator
and set e = x.format.UseCustomTopLevelSequenceSeparator <- e
/// <summary>
/// BSON pickler instance.
/// </summary>
type BsonSerializer([<O;D(null)>] ?typeConverter) =
inherit FsPicklerSerializer(new BsonPickleFormatProvider(), ?typeConverter = typeConverter)
/// FsPickler static methods.
type FsPickler =
/// <summary>
/// Initializes a new Json pickler instance.
/// </summary>
/// <param name="indent">indent out Json pickles.</param>
/// <param name="omitHeader">omit FsPickler header in Json pickles.</param>
/// <param name="typeConverter">specify a custom type name converter.</param>
static member CreateJson([<O;D(null)>] ?indent, [<O;D(null)>] ?omitHeader, [<O;D(null)>] ?typeConverter) =
new JsonSerializer(?indent = indent, ?omitHeader = omitHeader, ?typeConverter = typeConverter)
/// <summary>
/// Initializes a new Bson pickler instance.
/// </summary>
/// <param name="typeConverter">specify a custom type name converter.</param>
static member CreateBson([<O;D(null)>] ?typeConverter) =
new BsonSerializer(?typeConverter = typeConverter)

142
samples/F#/JsonWriter.fs Normal file
View File

@@ -0,0 +1,142 @@
namespace Nessos.FsPickler.Json
open System
open System.IO
open System.Collections.Generic
open Newtonsoft.Json
open Nessos.FsPickler
/// <summary>
/// Json format serializer.
/// </summary>
type internal JsonPickleWriter (jsonWriter : JsonWriter, omitHeader, indented, isTopLevelSequence, separator, leaveOpen) =
do
jsonWriter.Formatting <- if indented then Formatting.Indented else Formatting.None
jsonWriter.CloseOutput <- not leaveOpen
let isBsonWriter = match jsonWriter with :? Bson.BsonWriter -> true | _ -> false
let mutable depth = 0
let mutable isTopLevelSequenceHead = false
let mutable currentValueIsNull = false
let arrayStack = new Stack<int> ()
do arrayStack.Push Int32.MinValue
// do not write tag if omitting header or array element
let omitTag () = (omitHeader && depth = 0) || arrayStack.Peek() = depth - 1
interface IPickleFormatWriter with
member __.BeginWriteRoot (tag : string) =
if omitHeader then () else
jsonWriter.WriteStartObject()
writePrimitive jsonWriter false "FsPickler" jsonFormatVersion
writePrimitive jsonWriter false "type" tag
member __.EndWriteRoot () =
if not omitHeader then jsonWriter.WriteEnd()
member __.BeginWriteObject (tag : string) (flags : ObjectFlags) =
if not <| omitTag () then
jsonWriter.WritePropertyName tag
if flags.HasFlag ObjectFlags.IsNull then
currentValueIsNull <- true
jsonWriter.WriteNull()
elif flags.HasFlag ObjectFlags.IsSequenceHeader then
if isTopLevelSequence && depth = 0 then
isTopLevelSequenceHead <- true
else
jsonWriter.WriteStartArray()
arrayStack.Push depth
depth <- depth + 1
else
jsonWriter.WriteStartObject()
depth <- depth + 1
if flags = ObjectFlags.None then ()
else
let flagCsv = mkFlagCsv flags
writePrimitive jsonWriter false "_flags" flagCsv
member __.EndWriteObject () =
if currentValueIsNull then
currentValueIsNull <- false
else
depth <- depth - 1
if arrayStack.Peek () = depth then
if isTopLevelSequence && depth = 0 then ()
else
jsonWriter.WriteEndArray()
arrayStack.Pop () |> ignore
else
jsonWriter.WriteEndObject()
member __.SerializeUnionCaseNames = true
member __.PreferLengthPrefixInSequences = false
member __.WriteNextSequenceElement hasNext =
if isTopLevelSequence && depth = 1 then
if isTopLevelSequenceHead then
isTopLevelSequenceHead <- false
else
jsonWriter.WriteWhitespace separator
member __.WriteCachedObjectId id = writePrimitive jsonWriter false "id" id
member __.WriteBoolean (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteByte (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteSByte (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteInt16 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteInt32 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteInt64 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteUInt16 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteUInt32 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteUInt64 (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteSingle (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteDouble (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteDecimal (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag (string value)
member __.WriteChar (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteString (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteBigInteger (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag (string value)
member __.WriteGuid (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteTimeSpan (tag : string) value = writePrimitive jsonWriter (omitTag ()) tag (string value)
// BSON spec mandates the use of Unix time;
// this has millisecond precision which results in loss of accuracy w.r.t. ticks
// since the goal of FsPickler is to offer faithful representations of .NET objects
// we choose to override the spec and serialize ticks outright.
// see also https://json.codeplex.com/discussions/212067
member __.WriteDate (tag : string) value =
if isBsonWriter then
writePrimitive jsonWriter (omitTag ()) tag value.Ticks
else
writePrimitive jsonWriter (omitTag ()) tag value
member __.WriteBytes (tag : string) (value : byte []) =
if not <| omitTag () then
jsonWriter.WritePropertyName tag
if obj.ReferenceEquals(value, null) then
jsonWriter.WriteNull()
else
jsonWriter.WriteValue value
member __.IsPrimitiveArraySerializationSupported = false
member __.WritePrimitiveArray _ _ = raise <| NotSupportedException()
member __.Dispose () = jsonWriter.Flush()

View File

@@ -0,0 +1,68 @@
namespace Nessos.FsPickler.Tests
open PerfUtil
open PerfUtil.NUnit
open NUnit.Framework
open Nessos.FsPickler
open Nessos.FsPickler.Json
[<AbstractClass>]
type PerfTester () =
inherit NUnitPerf<Serializer> ()
let tests = PerfTest.OfModuleMarker<PerformanceTests.Marker> ()
override __.PerfTests = tests
type ``Serializer Comparison`` () =
inherit PerfTester()
let fsp = FsPickler.initBinary()
let bfs = new BinaryFormatterSerializer() :> Serializer
let ndc = new NetDataContractSerializer() :> Serializer
let jdn = new JsonDotNetSerializer() :> Serializer
let bdn = new JsonDotNetBsonSerializer () :> Serializer
let pbn = new ProtoBufSerializer() :> Serializer
let ssj = new ServiceStackJsonSerializer() :> Serializer
let sst = new ServiceStackTypeSerializer() :> Serializer
let comparer = new WeightedComparer(spaceFactor = 0.2, leastAcceptableImprovementFactor = 1.)
let tester = new ImplementationComparer<_>(fsp, [bfs;ndc;jdn;bdn;pbn;ssj;sst], throwOnError = true, warmup = true, comparer = comparer)
override __.PerfTester = tester :> _
type ``FsPickler Formats Comparison`` () =
inherit PerfTester ()
let binary = FsPickler.initBinary()
let json = FsPickler.initJson()
let bson = FsPickler.initBson()
let xml = FsPickler.initXml()
let tester = new ImplementationComparer<_>(binary, [json ; bson; xml], warmup = true, throwOnError = false)
override __.PerfTester = tester :> _
type ``Past FsPickler Versions Comparison`` () =
inherit PerfTester ()
let persistResults = true
let persistenceFile = "fspPerf.xml"
let fsp = FsPickler.initBinary()
let version = typeof<FsPickler>.Assembly.GetName().Version
let comparer = new WeightedComparer(spaceFactor = 0.2, leastAcceptableImprovementFactor = 0.8)
let tester =
new PastImplementationComparer<Serializer>(
fsp, version, historyFile = persistenceFile, throwOnError = true, warmup = true, comparer = comparer)
override __.PerfTester = tester :> _
[<TestFixtureTearDown>]
member __.Persist() =
if persistResults then tester.PersistCurrentResults ()

View File

@@ -0,0 +1,207 @@
namespace Nessos.FsPickler.Tests
open System
open System.Collections.Generic
open PerfUtil
open Nessos.FsPickler
open Nessos.FsPickler.Tests.Serializer
open Nessos.FsPickler.Tests.TestTypes
module PerformanceTests =
type Marker = class end
let guid = Guid.NewGuid()
[<PerfTest(1000)>]
let ``Value: Guid`` s = roundtrip guid s
let date = DateTime.Now
[<PerfTest(1000)>]
let ``Value: DateTime`` s = roundtrip date s
[<PerfTest(10000)>]
let ``Value: String`` s = roundtrip stringValue s
let boxed = box ([| 1 .. 1000 |], "lorem ipsum")
[<PerfTest(1000)>]
let ``Boxed Object`` s = roundtrip boxed s
let fsClass = new Class(42, stringValue)
[<PerfTest(10000)>]
let ``Class: Simple F# Class`` s = roundtrip fsClass s
let serializableClass = new SerializableClass<_>(42, stringValue, [|1..1000|])
[<PerfTest(10000)>]
let ``Class: ISerializable`` s = roundtrip serializableClass s
let boxedClass = box(Some 42)
[<PerfTest(10000)>]
let ``Subtype Resolution`` s = roundtrip boxedClass s
let floatArray = Array.init 100000 (fun i -> float i)
[<PerfTest(10)>]
let ``Array: Float`` s = roundtrip floatArray s
let intArray = Array.init 100000 id
[<PerfTest(10)>]
let ``Array: Int`` s = roundtrip intArray s
let stringArray = Array.init 10000 (fun i -> stringValue + string i)
[<PerfTest(100)>]
let ``Array: String`` s = roundtrip stringArray s
let kvarr = [|1..10000|] |> Array.map (fun i -> i, string i)
[<PerfTest(100)>]
let ``Array: Key-Value Pairs`` s = roundtrip kvarr s
let duArray = [| for i in 1 .. 10000 -> (Something ("asdasdasdas", i)) |]
[<PerfTest(100)>]
let ``Array: Discriminated Unions`` s = roundtrip duArray s
let objArray =
[|
box 2; box 3; box "hello" ; box <| Some 3; box(2,3) ;
box <| new Class(2, stringValue) ; box <| new SerializableClass<int option>(2, stringValue, Some 12);
box stringValue
|]
[<PerfTest(1000)>]
let ``Array: Objects`` s = roundtrip objArray s
let array3D = Array3D.init 100 100 100 (fun i j k -> float (i * j + k))
[<PerfTest(10)>]
let ``Array: Rank-3 Float`` s = roundtrip array3D s
let bclDict = dict [ for i in 1 .. 1000 -> (string i, i)]
[<PerfTest(100)>]
let ``.NET Dictionary`` s = roundtrip bclDict s
let bclStack = new Stack<string>([for i in 1 .. 1000 -> string i])
[<PerfTest(100)>]
let ``.NET Stack`` s = roundtrip bclStack s
let bclList = new List<string * int>([for i in 1 .. 1000 -> string i, i])
[<PerfTest(100)>]
let ``.NET List`` s = roundtrip bclList s
let bclSet = new SortedSet<_>([for i in 1 .. 1000 -> string i])
[<PerfTest(100)>]
let ``.NET Set`` s = roundtrip bclSet s
let smallTuple = (1, DateTime.Now,"hello")
[<PerfTest(10000)>]
let ``FSharp: Tuple Small`` s = roundtrip smallTuple s
let largeTuple = (stringValue, 1, 2, 3, true, "", Some(3.14, [2]), 3, 2, 1, stringValue)
[<PerfTest(10000)>]
let ``FSharp: Tuple Large`` s =
roundtrip largeTuple s
let intList = [1..1000]
[<PerfTest(1000)>]
let ``FSharp: List Int`` s = roundtrip intList s
let stringList = [ for i in 1 .. 1000 -> stringValue + string i ]
[<PerfTest(1000)>]
let ``FSharp: List String`` s = roundtrip stringList s
let pairList = [ for i in 1 .. 1000 -> (string i, i) ]
[<PerfTest(1000)>]
let ``FSharp: List Key-Value`` s = roundtrip pairList s
let nestedLst = let n = [1..1000] in [for _ in 1 .. 100 -> n]
[<PerfTest(1000)>]
let ``FSharp: List Nested`` s = roundtrip nestedLst s
let union = SomethingElse(stringValue, 42, box (Some 42))
[<PerfTest(10000)>]
let ``FSharp: Union`` s = roundtrip union s
let record = { Int = 42 ; String = stringValue ; Tuple = (13, "") }
[<PerfTest(10000)>]
let ``FSharp: Record`` s = roundtrip record s
let peano = int2Peano 100
[<PerfTest(100)>]
let ``FSharp: Peano Rectype`` s = roundtrip peano s
let closure = (@) [ Some([1..100], Set.ofList [1..100]) ]
[<PerfTest(1000)>]
let ``FSharp: Curried Function`` s = roundtrip closure s
let binTree = mkTree 10
[<PerfTest(100)>]
let ``FSharp: Binary Tree`` s = roundtrip binTree s
let intSet = [1..1000] |> List.map string |> set
[<PerfTest(1000)>]
let ``FSharp: Set`` s = roundtrip intSet s
let fsMap = [1..1000] |> Seq.map (fun i -> (string i,i)) |> Map.ofSeq
[<PerfTest(1000)>]
let ``FSharp: Map`` s = roundtrip fsMap s
let testType = typeof<int * string option * Map<int * string [], string ref option>>
[<PerfTest(1000)>]
let ``Reflection: Type`` s = roundtrip testType s
let quotationSmall = <@ fun x -> pown 2 x @>
let quotationLarge =
<@
async {
let rec fibAsync n =
async {
match n with
| _ when n < 0 -> return invalidArg "negative" "n"
| _ when n < 2 -> return n
| n ->
let! fn = fibAsync (n-1)
let! fnn = fibAsync (n-2)
return fn + fnn
}
let! values = [1..100] |> Seq.map fibAsync |> Async.Parallel
return Seq.sum values
}
@>
[<PerfTest(10000)>]
let ``FSharp: Quotation Small`` s = roundtrip quotationSmall s
[<PerfTest(1000)>]
let ``FSharp: Quotation Large`` s = roundtrip quotationLarge s