Skip to content

Commit 01d5fb0

Browse files
authored
Reduced option type allocations (#493)
* Reduced `option` type allocations * Fixed bug converting `option` to `voption` * Fix for missing `FsToolkit.ErrorHandling` in the type provider project
1 parent aeaf698 commit 01d5fb0

File tree

14 files changed

+237
-244
lines changed

14 files changed

+237
-244
lines changed

src/FSharp.Data.GraphQL.Client.DesignTime/FSharp.Data.GraphQL.Client.DesignTime.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<ExcludeAssets>contentFiles;runtime</ExcludeAssets>
2020
</PackageReference>
2121
<PackageReference Include="FSharp.TypeProviders.SDK" VersionOverride="8.0.2" />
22+
<PackageReference Include="FsToolkit.ErrorHandling" />
2223
<PackageReference Include="FParsec" />
2324
<PackageReference Include="Microsoft.Extensions.Http">
2425
<PrivateAssets>all</PrivateAssets>

src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,14 @@ module internal ProvidedInterface =
117117

118118
type internal RecordPropertyMetadata =
119119
{ Name : string
120-
Alias : string option
120+
Alias : string voption
121121
Description : string option
122122
DeprecationReason : string option
123123
Type : Type }
124124
member x.AliasOrName =
125125
match x.Alias with
126-
| Some x -> x
127-
| None -> x.Name
126+
| ValueSome x -> x
127+
| ValueNone -> x.Name
128128

129129
type internal ProvidedRecordTypeDefinition(className, baseType) =
130130
inherit ProvidedTypeDefinition(className, baseType, nonNullable = true)
@@ -157,7 +157,7 @@ module internal ProvidedRecord =
157157
metadata.Description |> Option.iter pdef.AddXmlDoc
158158
metadata.DeprecationReason |> Option.iter pdef.AddObsoleteAttribute
159159
pdef))
160-
let addConstructorDelayed (propertiesGetter : unit -> (string * string option * Type) list) =
160+
let addConstructorDelayed (propertiesGetter : unit -> (string * string voption * Type) list) =
161161
tdef.AddMembersDelayed(fun _ ->
162162
// We need to build a constructor that takes all optional properties wrapped in another option.
163163
// We need to do this because optional parameters have issues with non-nullable types
@@ -180,7 +180,7 @@ module internal ProvidedRecord =
180180
let properties = propertiesGetter()
181181
let optionalProperties, requiredProperties =
182182
properties
183-
|> List.map (fun (name, alias, t) -> Option.defaultValue name alias, t)
183+
|> List.map (fun (name, alias, t) -> ValueOption.defaultValue name alias, t)
184184
|> List.partition (fun (_, t) -> isOption t)
185185
if explicitOptionalParameters then
186186
let constructorProperties = requiredProperties @ optionalProperties
@@ -380,7 +380,7 @@ module internal ProvidedOperation =
380380
| _ -> t = typeof<Upload>
381381
variables |> Seq.exists (snd >> existsUploadType [])
382382
let runMethodOverloads : MemberInfo list =
383-
let operationName = Option.toObj operationDefinition.Name
383+
let operationName = ValueOption.toObj operationDefinition.Name
384384
methodOverloadDefinitions |> List.map (fun overloadParameters ->
385385
let variableNames = overloadParameters |> List.map fst |> List.filter (fun name -> name <> "runtimeContext")
386386
let invoker (args : Expr list) =
@@ -422,7 +422,7 @@ module internal ProvidedOperation =
422422
methodDef.AddXmlDoc("Executes the operation on the server and fetch its results.")
423423
upcast methodDef)
424424
let asyncRunMethodOverloads : MemberInfo list =
425-
let operationName = Option.toObj operationDefinition.Name
425+
let operationName = ValueOption.toObj operationDefinition.Name
426426
methodOverloadDefinitions |> List.map (fun overloadParameters ->
427427
let variableNames = overloadParameters |> List.map fst |> List.filter (fun name -> name <> "runtimeContext")
428428
let invoker (args : Expr list) =
@@ -601,7 +601,7 @@ module internal Provider =
601601
| TypeKind.SCALAR when field.Type.Name.IsSome ->
602602
let providedType = TypeMapping.mapScalarType uploadInputTypeName field.Type.Name.Value
603603
{ Name = field.Name
604-
Alias = None
604+
Alias = ValueNone
605605
Description = field.Description
606606
DeprecationReason = field.DeprecationReason
607607
Type = providedType }
@@ -613,7 +613,7 @@ module internal Provider =
613613
let itype = getSchemaType field.Type
614614
let providedType = resolveProvidedType itype
615615
{ Name = field.Name
616-
Alias = None
616+
Alias = ValueNone
617617
Description = field.Description
618618
DeprecationReason = field.DeprecationReason
619619
Type = providedType }
@@ -624,7 +624,7 @@ module internal Provider =
624624
| TypeKind.SCALAR when field.Type.Name.IsSome ->
625625
let providedType = TypeMapping.mapScalarType uploadInputTypeName field.Type.Name.Value
626626
{ Name = field.Name
627-
Alias = None
627+
Alias = ValueNone
628628
Description = field.Description
629629
DeprecationReason = None
630630
Type = providedType }
@@ -636,7 +636,7 @@ module internal Provider =
636636
let itype = getSchemaType field.Type
637637
let providedType = resolveProvidedType itype
638638
{ Name = field.Name
639-
Alias = None
639+
Alias = ValueNone
640640
Description = field.Description
641641
DeprecationReason = None
642642
Type = providedType }
@@ -798,22 +798,22 @@ module internal Provider =
798798
|> QueryValidationDesignTimeCache.getOrAdd key
799799
|> throwExceptionIfValidationFailed
800800
#endif
801-
let operationName : OperationName option =
801+
let operationName : OperationName voption =
802802
match args.[2] :?> string with
803803
| null | "" ->
804804
let operationDefinitions = queryAst.Definitions |> List.filter (function OperationDefinition _ -> true | _ -> false)
805805
match operationDefinitions with
806806
| opdef :: _ -> opdef.Name
807807
| _ -> failwith "Error parsing query. Can not choose a default operation: query document has no operation definitions."
808-
| x -> Some x
809-
let explicitOperationTypeName : TypeName option =
808+
| x -> ValueSome x
809+
let explicitOperationTypeName : TypeName voption =
810810
match args.[3] :?> string with
811-
| null | "" -> None
812-
| x -> Some x
811+
| null | "" -> ValueNone
812+
| x -> ValueSome x
813813
let operationDefinition =
814814
queryAst.Definitions
815-
|> List.choose (function OperationDefinition odef -> Some odef | _ -> None)
816-
|> List.find (fun d -> d.Name = operationName)
815+
|> Seq.vchoose (function OperationDefinition odef -> ValueSome odef | _ -> ValueNone)
816+
|> Seq.find (fun d -> d.Name = operationName)
817817
let operationAstFields =
818818
let infoMap = queryAst.GetInfoMap()
819819
match infoMap.TryFind(operationName) with
@@ -843,9 +843,9 @@ module internal Provider =
843843
let actualQuery = queryAst.ToQueryString(QueryStringPrintingOptions.IncludeTypeNames).Replace("\r\n", "\n")
844844
let className =
845845
match explicitOperationTypeName, operationDefinition.Name with
846-
| Some name, _ -> name.FirstCharUpper()
847-
| None, Some name -> name.FirstCharUpper()
848-
| None, None -> "Operation" + actualQuery.MD5Hash()
846+
| ValueSome name, _ -> name.FirstCharUpper()
847+
| ValueNone, ValueSome name -> name.FirstCharUpper()
848+
| ValueNone, ValueNone -> "Operation" + actualQuery.MD5Hash()
849849
let metadata = getOperationMetadata(schemaTypes, uploadInputTypeName, enumProvidedTypes, operationAstFields, operationTypeRef, explicitOptionalParameters)
850850
let operationTypeName : TypeName =
851851
match operationTypeRef.Name with

src/FSharp.Data.GraphQL.Server.AspNetCore/GraphQLRequestHandler.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ type GraphQLRequestHandler<'Root> (
161161
let checkAnonymousFieldsOnly (ctx: HttpContext) = taskResult {
162162
let! gqlRequest = ctx.TryBindJsonAsync<GQLRequestContent>(GQLRequestContent.expectedJSON)
163163
let! ast = Parser.parseOrIResult ctx.Request.Path.Value gqlRequest.Query
164-
let operationName = gqlRequest.OperationName |> Skippable.toOption
164+
let operationName = gqlRequest.OperationName |> Skippable.toValueOption
165165

166166
let createParsedContent() = {
167167
Query = gqlRequest.Query

src/FSharp.Data.GraphQL.Server/Execution.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ let internal findOperation doc opName =
207207
| [def], _ -> Some def
208208
| defs, name ->
209209
defs
210-
|> List.tryFind (fun def -> def.Name = name)
210+
|> List.tryFind (fun def -> def.Name = (name |> ValueOption.ofOption))
211211

212212
let private defaultResolveType possibleTypesFn abstractDef : obj -> ObjectDef =
213213
let possibleTypes = possibleTypesFn abstractDef

src/FSharp.Data.GraphQL.Server/Planning.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ let private objectInfo (ctx: PlanningContext) (parentDef: ObjectDef) field inclu
7979
let rec private abstractionInfo (ctx : PlanningContext) (parentDef : AbstractDef) field typeCondition includer =
8080
let objDefs = ctx.Schema.GetPossibleTypes parentDef
8181
match typeCondition with
82-
| None ->
82+
| ValueNone ->
8383
objDefs
8484
|> Array.choose (fun objDef ->
8585
match tryFindDef ctx.Schema objDef field with
@@ -96,7 +96,7 @@ let rec private abstractionInfo (ctx : PlanningContext) (parentDef : AbstractDef
9696
Some (objDef.Name, data)
9797
| None -> None)
9898
|> Map.ofArray
99-
| Some typeName ->
99+
| ValueSome typeName ->
100100
match objDefs |> Array.tryFind (fun o -> o.Name = typeName) with
101101
| Some objDef ->
102102
match tryFindDef ctx.Schema objDef field with
@@ -115,7 +115,7 @@ let rec private abstractionInfo (ctx : PlanningContext) (parentDef : AbstractDef
115115
| None ->
116116
match ctx.Schema.TryFindType typeName with
117117
| Some (Abstract abstractDef) ->
118-
abstractionInfo ctx abstractDef field None includer
118+
abstractionInfo ctx abstractDef field ValueNone includer
119119
| _ ->
120120
let pname = parentDef :?> NamedDef
121121
Debug.Fail "Must be prevented by validation"
@@ -149,8 +149,8 @@ let private getIncluder (directives: Directive list) parentIncluder : Includer =
149149

150150
let private doesFragmentTypeApply (schema: ISchema) fragment (objectType: ObjectDef) =
151151
match fragment.TypeCondition with
152-
| None -> true
153-
| Some typeCondition ->
152+
| ValueNone -> true
153+
| ValueSome typeCondition ->
154154
match schema.TryFindType typeCondition with
155155
| None -> false
156156
| Some conditionalType when conditionalType.Name = objectType.Name -> true
@@ -243,7 +243,7 @@ let rec private plan (ctx : PlanningContext) (info : ExecutionInfo) : ExecutionI
243243
let inner = plan ctx { info with ParentDef = info.ReturnDef; ReturnDef = downcast returnDef; }
244244
{ info with Kind = ResolveCollection inner }
245245
| Abstract _ ->
246-
planAbstraction ctx info.Ast.SelectionSet info (ref []) None
246+
planAbstraction ctx info.Ast.SelectionSet info (ref []) ValueNone
247247
| _ ->
248248
Debug.Fail "Must be prevented by validation"
249249
failwith "Invalid Return Type in Planning!"

src/FSharp.Data.GraphQL.Shared/Ast.fs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ and Definition =
3131
/// 2.2.1 Operations
3232
and OperationDefinition = {
3333
OperationType : OperationType
34-
Name : string option
34+
Name : string voption
3535
VariableDefinitions : VariableDefinition list
3636
Directives : Directive list
3737
SelectionSet : Selection list
@@ -64,7 +64,7 @@ and Selection =
6464
/// 2.2.3 Fields
6565
and Field = {
6666
/// 2.2.5 Field Alias
67-
Alias : string option
67+
Alias : string voption
6868
Name : string
6969
Arguments : Argument list
7070
Directives : Directive list
@@ -73,8 +73,8 @@ and Field = {
7373

7474
member x.AliasOrName =
7575
match x.Alias with
76-
| Some alias -> alias
77-
| None -> x.Name
76+
| ValueSome alias -> alias
77+
| ValueNone -> x.Name
7878

7979
/// 2.2.4 Arguments
8080
and Argument = { Name : string; Value : InputValue }
@@ -83,9 +83,9 @@ and Argument = { Name : string; Value : InputValue }
8383
and FragmentSpread = { Name : string; Directives : Directive list }
8484

8585
and FragmentDefinition = {
86-
Name : string option
86+
Name : string voption
8787
/// 2.2.6.1 Type Conditions
88-
TypeCondition : string option
88+
TypeCondition : string voption
8989
Directives : Directive list
9090
SelectionSet : Selection list
9191
}
@@ -146,7 +146,7 @@ and ObjectTypeDefinition = { Name : string; Interfaces : string[]; Fields : Fiel
146146

147147
and FieldDefinition = { Name : string; Arguments : InputValueDefinition[]; Type : InputType }
148148

149-
and InputValueDefinition = { Name : string; Type : InputType; DefaultValue : InputValue option }
149+
and InputValueDefinition = { Name : string; Type : InputType; DefaultValue : InputValue voption }
150150

151151
and InterfaceTypeDefinition = { Name : string; Fields : FieldDefinition[] }
152152

0 commit comments

Comments
 (0)