diff --git a/Benchmarks/Benchmarks/CollectionSchema.swift b/Benchmarks/Benchmarks/CollectionSchema.swift new file mode 100644 index 00000000..c0a7b9f3 --- /dev/null +++ b/Benchmarks/Benchmarks/CollectionSchema.swift @@ -0,0 +1,81 @@ +import GraphQL + +// Contains a basic schema that holds a single, large static array. Used for testing processing throughput and +// large object encoding + +struct CollectionItem: Codable, Sendable { + let value1: String + let value2: Int +} + +let collectionItem = try! GraphQLObjectType( + name: "CollectionItem", + fields: [ + "value1": .init( + type: GraphQLString, + resolve: { source, _, _, _ in + (source as! CollectionItem).value1 + } + ), + "value2": .init( + type: GraphQLInt, + resolve: { source, _, _, _ in + (source as! CollectionItem).value2 + } + ) + ] +) + +func collectionSchema(count: Int) -> (schema: GraphQLSchema, collection: [CollectionItem]) { + let staticCollection: [CollectionItem] = (0.. GraphQLSchema { + let staticCollection: [CollectionItem] = (0.. Void = { + let encoder = JSONEncoder() + Benchmark("graphql") { _ in let result = try await graphql( schema: starWarsSchema, @@ -21,4 +24,71 @@ let benchmarks: @Sendable () -> Void = { """ ) } + + // Benchmarks the time to push a large static array through the GraphQL resolution system + Benchmark("resolution") { _, schema in + let result = try await graphql( + schema: schema, + request: """ + query { + collection { + value1 + value2 + } + } + """ + ) + } setup: { + return collectionSchema(count: 10_000).schema + } + + // Benchmarks the large static array exposed as a custom scalar + // This avoids all the GraphQL resolution of each element item, and as such is way faster. + Benchmark("resolution:scalar") { _, schema in + let result = try await graphql( + schema: schema, + request: """ + query { + collection + } + """ + ) + } setup: { + return collectionScalarSchema(count: 10_000) + } + + // Benchmarks the time to encode a GraphQLResult + Benchmark("encoding:GraphQLResult") { _, result in + let result = try encoder.encode(result) + } setup: { + return try await graphql( + schema: collectionSchema(count: 100_000).schema, + request: """ + query { + collection { + value1 + value2 + } + } + """ + ) + } + + // Benchmarks the baseline time to encode a strongly typed Swift type (for comparison with encoding a GraphQLResult with `Map` types) + Benchmark("encoding:baseline") { _, result in + let result = try encoder.encode(result) + } setup: { + return BaselineResult( + query: .init( + collection: collectionSchema(count: 100_000).collection + ) + ) + } + struct BaselineResult: Codable { + let query: Query + + struct Query: Codable { + let collection: [CollectionItem] + } + } }