Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions Benchmarks/Benchmarks/CollectionSchema.swift
Original file line number Diff line number Diff line change
@@ -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..<count).map {
CollectionItem(value1: "\($0)", value2: $0)
}
let schema = try! GraphQLSchema(
query: .init(
name: "Query",
fields: [
"collection": .init(
type: GraphQLList(collectionItem),
resolve: {_, _, _, _ in
return staticCollection
}
)
]
),
types: [collectionItem]
)
return (schema, staticCollection)
}



func collectionScalarSchema(count: Int) -> GraphQLSchema {
let staticCollection: [CollectionItem] = (0..<count).map {
CollectionItem(value1: "\($0)", value2: $0)
}
let collectionItemsScalar = try! GraphQLScalarType(
name: "CollectionItems",
serialize: { value in
.array((value as! [CollectionItem]).map { item in
.dictionary([
"value1": .string(item.value1),
"value2": .int(item.value2),
])
})
}
)
return try! GraphQLSchema(
query: .init(
name: "Query",
fields: [
"collection": .init(
type: collectionItemsScalar,
resolve: { _, _, _, _ in
return staticCollection
}
)
]
),
types: [collectionItemsScalar]
)
}
70 changes: 70 additions & 0 deletions Benchmarks/Benchmarks/GraphQLBenchmarks.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Benchmark
import class Foundation.JSONEncoder
import GraphQL

let benchmarks: @Sendable () -> Void = {
let encoder = JSONEncoder()

Benchmark("graphql") { _ in
let result = try await graphql(
schema: starWarsSchema,
Expand All @@ -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]
}
}
}
Loading