@@ -25,6 +25,13 @@ module Json =
2525 Decode: Decoder < 'T >
2626 }
2727
28+ ///
29+ /// Tiny payloads fit comfortably in the old ` 128 ` -byte buffer, but the
30+ /// benchmark runner now measures batches of ` 100 ` records where repeated
31+ /// growth and copy steps dominate allocation churn. Starting larger keeps
32+ /// the hot JSON path closer to realistic message sizes.
33+ let private defaultSerializeBufferCapacity = 4096
34+
2835 type internal DecodePathSegment =
2936 | Property of string
3037 | Index of int
@@ -852,13 +859,25 @@ module Json =
852859 fields
853860 |> Array.mapi ( fun i f ->
854861 let codec = compileUntyped f.Schema
862+ let encodedName = " \" " + f.Name + " \" :"
855863
856864 {|
857865 Name = f.Name
866+ EncodedName = encodedName
858867 Index = i
859868 Codec = codec
860869 |})
861870
871+ ///
872+ /// Object decode used to linearly scan every field name for every
873+ /// property in the payload. A fixed lookup table keeps the compiled
874+ /// cost up front and removes repeated per-property scans.
875+ let fieldIndices = Dictionary< string, int>( compiledFields.Length)
876+
877+ do
878+ for field in compiledFields do
879+ fieldIndices[ field.Name] <- field.Index
880+
862881 let encoder ( writer : IByteWriter ) ( vObj : obj ) =
863882 writer.WriteByte( 123 uy)
864883 let mutable first = true
@@ -867,10 +886,7 @@ module Json =
867886 if not first then
868887 writer.WriteByte( 44 uy)
869888
870- writer.WriteByte( 34 uy)
871- writer.WriteString( f.Name)
872- writer.WriteByte( 34 uy)
873- writer.WriteByte( 58 uy)
889+ writer.WriteString( f.EncodedName)
874890 f.Codec.Encode writer ( fields[ f.Index]. GetValue vObj)
875891 first <- false
876892
@@ -900,17 +916,10 @@ module Json =
900916 failwith " Expected :"
901917
902918 let valSrc = Runtime.skipWhitespace ( afterColon.Advance( 1 ))
903- let mutable found = false
904- let mutable i = 0
905-
906- while i < compiledFields.Length && not found do
907- let f = compiledFields[ i]
908919
909- if f.Name = key then
910- fieldSources[ f.Index] <- valSrc
911- found <- true
912- else
913- i <- i + 1
920+ match fieldIndices.TryGetValue( key) with
921+ | true , index -> fieldSources[ index] <- valSrc
922+ | false , _ -> ()
914923
915924 let afterVal = Runtime.skipWhitespace ( Runtime.skipValue valSrc)
916925
@@ -1104,7 +1113,7 @@ module Json =
11041113
11051114 /// Serializes a value to JSON using a previously compiled codec.
11061115 let serialize ( codec : Codec < 'T >) ( value : 'T ) =
1107- let writer = ResizableBuffer.Create( 128 )
1116+ let writer = ResizableBuffer.Create( defaultSerializeBufferCapacity )
11081117 codec.Encode writer value
11091118 Encoding.UTF8.GetString( writer.InternalData, 0 , writer.InternalCount)
11101119
0 commit comments