Instantly share code, notes, and snippets.

Embed
What would you like to do?
dotnet build -c Release benchmarks/Chiron.Benchmarks/Chiron.Benchmarks.fsproj && \
dotnet benchmarks/Chiron.Benchmarks/bin/Release/netcoreapp2.0/Chiron.Benchmarks.dll --class ParseTest
// * Summary *
BenchmarkDotNet=v0.10.14, OS=macOS High Sierra 10.13.5 (17F77) [Darwin 17.6.0]
Intel Core i7-7920HQ CPU 3.10GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=2.1.200
[Host] : .NET Core 2.0.7 (CoreCLR 4.6.0.0, CoreFX 4.6.26403.03), 64bit RyuJIT
MediumRun : .NET Core 2.0.7 (CoreCLR 4.6.0.0, CoreFX 4.6.26403.03), 64bit RyuJIT
Job=MediumRun LaunchCount=2 TargetCount=15
WarmupCount=10
Method | Name | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
----------- |----------- |---------------:|------------:|--------------:|----------:|----------:|---------:|-----------:|
Chiron_New | error | 3.423 us | 0.0672 us | 0.0963 us | 0.2823 | - | - | 1200 B |
Newtonsoft | error | 1.926 us | 0.1739 us | 0.2380 us | 1.6289 | - | - | 6840 B |
Chiron_New | fparsec | 19.657 us | 0.2533 us | 0.3551 us | 1.4648 | - | - | 6200 B |
Newtonsoft | fparsec | 9.459 us | 0.0957 us | 0.1432 us | 3.2349 | - | - | 13576 B |
Chiron_New | prettyuser | 48.209 us | 0.7862 us | 1.1768 us | 3.9063 | - | - | 16632 B |
Newtonsoft | prettyuser | 20.805 us | 0.1651 us | 0.2259 us | 5.4626 | - | - | 22968 B |
Chiron_New | social | 125,279.691 us | 825.6099 us | 1,210.1683 us | 5812.5000 | 1937.5000 | 625.0000 | 30154333 B |
Newtonsoft | social | NA | NA | NA | N/A | N/A | N/A | N/A |
Chiron_New | user | 45.557 us | 0.4152 us | 0.6085 us | 3.9063 | - | - | 16632 B |
Newtonsoft | user | 20.237 us | 0.2521 us | 0.3695 us | 5.4626 | - | - | 22968 B |
Benchmarks with issues:
ParseTest.Newtonsoft: MediumRun(LaunchCount=2, TargetCount=15, WarmupCount=10) [Name=social]
namespace ChironB.Benchmarks
open Chiron
open BenchmarkDotNet.Attributes
open Newtonsoft.Json
open Newtonsoft.Json.Linq
module Bench =
open System.IO
open System.Text
let resetStream (stream : #Stream) =
stream.Seek(0L, SeekOrigin.Begin) |> ignore
module Chiron =
let inline parse (stream: #Stream): Json =
let reader = new StreamReader(stream)
reader.ReadToEnd()
|> Json.parse
|> JsonResult.getOrThrow
// let inline parseAndDeserialize (stream : #Stream) : 'a =
// let reader = new StreamReader(stream)
// reader.ReadToEnd()
// |> Json.parse
// |> Json.deserialize
module JsonNET =
let serializer = JsonSerializer.CreateDefault()
let inline parse (stream: #Stream): JObject =
let jsonReader = new StreamReader(stream, Encoding.UTF8)
let reader = new JsonTextReader(jsonReader, CloseInput = false)
JObject.Load reader
[<Config(typeof<CoreConfig>)>]
type ParseTest () =
let mutable jsonStream = null
let mutable jsonString = null
[<Setup>]
member this.Setup () =
jsonString <- loadJsonResourceAsString this.Name
jsonStream <- loadJsonResource this.Name
[<Params("error", "fparsec", "user", "prettyuser", "social")>]
member val Name = "<null>" with get, set
[<Benchmark>]
member __.Chiron_New (): Chiron.JsonResult<Chiron.Json> =
Chiron.Parsing.Json.parse jsonString
[<Benchmark>]
member __.Newtonsoft () =
Bench.resetStream jsonStream
Bench.JsonNET.parse jsonStream
[<Config(typeof<CoreConfig>)>]
type FormatTest () =
let mutable jsonN = Chiron.Json.Null
[<Setup>]
member this.Setup () =
jsonN <-
loadJsonResourceAsString this.Name
|> Chiron.Parsing.Json.parse
|> Chiron.JsonResult.getOrThrow
[<Params("error", "fparsec", "user", "prettyuser", "social")>]
member val Name = "<null>" with get, set
[<Benchmark>]
member __.Chiron_New () =
Chiron.Formatting.Json.format jsonN
[<Config(typeof<CoreConfig>)>]
type FormatVariableLengthStrings () =
let mutable simpleJson = Chiron.Json.Null
let mutable escapedJson = Chiron.Json.Null
[<Params(10, 100, 1000, 10000, 100000)>]
member val public strlen = 1 with get, set
[<Setup>]
member x.Setup () =
let simple = String.replicate x.strlen "a"
simpleJson <- Chiron.Json.String simple
let escaped = String.replicate (x.strlen / 10) "\\u0004\\n\\\""
escapedJson <- Chiron.Json.String escaped
[<Benchmark>]
member __.Simple_New () =
Chiron.Formatting.Json.format simpleJson
[<Benchmark>]
member __.Escaped_New () =
Chiron.Formatting.Json.format escapedJson
@ScottHutchinson

This comment has been minimized.

ScottHutchinson commented Jul 29, 2018

So, the way I read these results is: Newtonsoft is faster than Chiron, but uses more memory and does more garbage collecting. Right?

@gusty

This comment has been minimized.

gusty commented Jul 30, 2018

You can get the best of both worlds by using Fleece which supports NewtonSoft as Json encoder/decoder.

Actually Fleece is the original F# project (the original is Haskell's AESON) while Chiron seems to be a bad copy of Fleece, which implements its own parsers (a bad idea).

@wallymathieu

This comment has been minimized.

wallymathieu commented Aug 4, 2018

Looks like the performance of Newtonsoft is heavily dependant on where it runs. There are multiple compilation flags. For instance some IL-emit code is not done in netcore, while it's done for some versions of net\d+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment