Browse Source

[vapor] add sqlkit + raw postgres tests, separate fluent tests (#5862)

Tanner 5 years ago
parent
commit
e4328004a1

+ 0 - 10
frameworks/Swift/vapor/app/Sources/ServerMiddleware.swift

@@ -1,10 +0,0 @@
-import Vapor
-
-struct ServerMiddleware: Middleware {
-    func respond(to request: Request, chainingTo next: Responder) -> EventLoopFuture<Response> {
-        next.respond(to: request).map { response in
-            response.headers.add(name: .server, value: "Vapor")
-            return response
-        }
-    }
-}

+ 75 - 24
frameworks/Swift/vapor/benchmark_config.json

@@ -1,28 +1,79 @@
 {
   "framework": "vapor",
-  "tests": [
-    {
-      "default": {
-        "plaintext_url": "/plaintext",
-        "json_url": "/json",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "port": 8080,
-        "approach": "Realistic",
-        "classification": "Fullstack",
-        "database": "Postgres",
-        "framework": "Vapor",
-        "language": "Swift",
-        "flavor": "None",
-        "orm": "Full",
-        "platform": "None",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "Vapor",
-        "notes": "",
-        "versus": "None"
-      }
+  "tests": [{
+    "default": {
+      "plaintext_url": "/plaintext",
+      "json_url": "/json",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "framework": "Vapor",
+      "language": "Swift",
+      "flavor": "None",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Vapor",
+      "notes": "",
+      "versus": "None"
+    },
+    "fluent": {
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "Vapor",
+      "language": "Swift",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Vapor",
+      "notes": "",
+      "versus": "None"
+    },
+    "sql-kit": {
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "Vapor",
+      "language": "Swift",
+      "flavor": "None",
+      "orm": "Micro",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Vapor",
+      "notes": "",
+      "versus": "None"
+    },
+    "postgres": {
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "Vapor",
+      "language": "Swift",
+      "flavor": "None",
+      "orm": "Raw",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Vapor",
+      "notes": "",
+      "versus": "None"
     }
-  ]
+  }]
 }

+ 20 - 0
frameworks/Swift/vapor/vapor-default/Package.swift

@@ -0,0 +1,20 @@
+// swift-tools-version:5.1
+import PackageDescription
+
+let package = Package(
+    name: "vapor-default",
+    platforms: [
+        .macOS(.v10_15)
+    ],
+    products: [
+        .executable(name: "app", targets: ["App"])
+    ],
+    dependencies: [
+        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
+    ],
+    targets: [
+        .target(name: "App", dependencies: [
+            "Vapor",
+        ], path: "Sources")
+    ]
+)

+ 22 - 0
frameworks/Swift/vapor/vapor-default/Sources/main.swift

@@ -0,0 +1,22 @@
+import Vapor
+
+var env = try Environment.detect()
+try LoggingSystem.bootstrap(from: &env)
+
+let app = Application(env)
+defer { app.shutdown() }
+
+app.http.server.configuration.serverName = "Vapor"
+
+app.logger.notice("💧 VAPOR")
+app.logger.notice("System.coreCount: \(System.coreCount)")
+
+app.get("plaintext") { req in
+    "Hello, world!"
+}
+
+app.get("json") { req in
+    ["message": "Hello, world!"]
+}
+
+try app.run()

+ 27 - 0
frameworks/Swift/vapor/vapor-fluent.dockerfile

@@ -0,0 +1,27 @@
+# ================================
+# Build image
+# ================================
+FROM vapor/swift:5.2 as build
+WORKDIR /build
+
+# Copy entire repo into container
+COPY ./vapor-fluent .
+
+# Compile with optimizations
+RUN swift build \
+	--enable-test-discovery \
+	-c release
+
+# ================================
+# Run image
+# ================================
+FROM vapor/ubuntu:18.04
+WORKDIR /run
+
+# Copy build artifacts
+COPY --from=build /build/.build/release /run
+
+# Copy Swift runtime libraries
+COPY --from=build /usr/lib/swift/ /usr/lib/swift/
+
+ENTRYPOINT ["./app", "serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]

+ 4 - 4
frameworks/Swift/vapor/app/Package.swift → frameworks/Swift/vapor/vapor-fluent/Package.swift

@@ -2,7 +2,7 @@
 import PackageDescription
 
 let package = Package(
-    name: "app",
+    name: "vapor-fluent",
     platforms: [
         .macOS(.v10_15)
     ],
@@ -10,9 +10,9 @@ let package = Package(
         .executable(name: "app", targets: ["App"])
     ],
     dependencies: [
-        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-rc"),
-        .package(url: "https://github.com/vapor/fluent.git", from: "4.0.0-rc"),
-        .package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0-rc"),
+        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
+        .package(url: "https://github.com/vapor/fluent.git", from: "4.0.0"),
+        .package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0"),
     ],
     targets: [
         .target(name: "App", dependencies: [

+ 0 - 0
frameworks/Swift/vapor/app/Sources/Utilities.swift → frameworks/Swift/vapor/vapor-fluent/Sources/Utilities.swift


+ 0 - 0
frameworks/Swift/vapor/app/Sources/World.swift → frameworks/Swift/vapor/vapor-fluent/Sources/World.swift


+ 1 - 1
frameworks/Swift/vapor/app/Sources/main.swift → frameworks/Swift/vapor/vapor-fluent/Sources/main.swift

@@ -8,7 +8,7 @@ try LoggingSystem.bootstrap(from: &env)
 let app = Application(env)
 defer { app.shutdown() }
 
-app.middleware.use(ServerMiddleware())
+app.http.server.configuration.serverName = "Vapor"
 
 app.logger.notice("💧 VAPOR")
 app.logger.notice("System.coreCount: \(System.coreCount)")

+ 27 - 0
frameworks/Swift/vapor/vapor-postgres.dockerfile

@@ -0,0 +1,27 @@
+# ================================
+# Build image
+# ================================
+FROM vapor/swift:5.2 as build
+WORKDIR /build
+
+# Copy entire repo into container
+COPY ./vapor-postgres .
+
+# Compile with optimizations
+RUN swift build \
+	--enable-test-discovery \
+	-c release
+
+# ================================
+# Run image
+# ================================
+FROM vapor/ubuntu:18.04
+WORKDIR /run
+
+# Copy build artifacts
+COPY --from=build /build/.build/release /run
+
+# Copy Swift runtime libraries
+COPY --from=build /usr/lib/swift/ /usr/lib/swift/
+
+ENTRYPOINT ["./app", "serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]

+ 22 - 0
frameworks/Swift/vapor/vapor-postgres/Package.swift

@@ -0,0 +1,22 @@
+// swift-tools-version:5.1
+import PackageDescription
+
+let package = Package(
+    name: "vapor-sql-kit",
+    platforms: [
+        .macOS(.v10_15)
+    ],
+    products: [
+        .executable(name: "app", targets: ["App"])
+    ],
+    dependencies: [
+        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
+        .package(url: "https://github.com/vapor/postgres-kit.git", from: "2.0.0"),
+    ],
+    targets: [
+        .target(name: "App", dependencies: [
+            "PostgresKit",
+            "Vapor"
+        ], path: "Sources")
+    ]
+)

+ 25 - 0
frameworks/Swift/vapor/vapor-postgres/Sources/Utilities.swift

@@ -0,0 +1,25 @@
+import Vapor
+
+extension Int {
+    func bounded(to range: ClosedRange<Int>) -> Int {
+        switch self {
+        case ...range.lowerBound:
+            return range.lowerBound
+        case range.upperBound...:
+            return range.upperBound
+        default:
+            return self
+        }
+    }
+}
+
+extension System {
+    // tfb-server (aka, citrine) uses 28 hyper-threaded cores
+    // postgresql.conf specifies max_connections = 2000
+    //
+    // 2000 / (28 * 2) = 35.7 (theoretical max)
+    //
+    // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Environment#citrine-self-hosted
+    // https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/toolset/databases/postgres/postgresql.conf#L64
+    static var maxConnectionsPerEventLoop: Int { 32 }
+}

+ 6 - 0
frameworks/Swift/vapor/vapor-postgres/Sources/World.swift

@@ -0,0 +1,6 @@
+import Vapor
+
+struct World: Content {
+    var id: Int32?
+    var randomnumber: Int
+}

+ 63 - 0
frameworks/Swift/vapor/vapor-postgres/Sources/main.swift

@@ -0,0 +1,63 @@
+import PostgresKit
+import Vapor
+
+var env = try Environment.detect()
+try LoggingSystem.bootstrap(from: &env)
+
+let app = Application(env)
+defer { app.shutdown() }
+
+app.http.server.configuration.serverName = "Vapor"
+
+app.logger.notice("💧 VAPOR")
+app.logger.notice("System.coreCount: \(System.coreCount)")
+app.logger.notice("System.maxConnectionsPerEventLoop: \(System.maxConnectionsPerEventLoop)")
+
+let pools = EventLoopGroupConnectionPool(
+    source: PostgresConnectionSource(configuration: .init(
+        hostname: "tfb-database",
+        username: "benchmarkdbuser",
+        password: "benchmarkdbpass",
+        database: "hello_world"
+    )), 
+    maxConnectionsPerEventLoop: System.maxConnectionsPerEventLoop,
+    on: app.eventLoopGroup
+)
+
+extension Request {
+    func db(_ pools: EventLoopGroupConnectionPool<PostgresConnectionSource>) -> PostgresDatabase {
+        pools.pool(for: self.eventLoop).database(logger: self.logger)
+    }
+}
+
+app.get("db") { req in
+    req.db(pools).query("SELECT id, randomnumber FROM World WHERE id = $1", [
+        PostgresData(int32: .random(in: 1...10_000))
+    ]).map {
+        $0.first
+    }.unwrap(or: Abort(.notFound)).map {
+        World(
+            id: $0.column("id")?.int32 ?? 0,
+            randomnumber: $0.column("randomnumber")?.int ?? 0
+        )
+    }
+}
+
+app.get("queries") { req -> EventLoopFuture<[World]> in
+    let queries = (req.query["queries"] ?? 1).bounded(to: 1...500)
+    let db = req.db(pools)
+    return (0 ..< queries).map { _ -> EventLoopFuture<World> in
+        db.query("SELECT id, randomnumber FROM World WHERE id = $1", [
+            PostgresData(int32: .random(in: 1...10_000))
+        ]).map {
+            $0.first
+        }.unwrap(or: Abort(.notFound)).map {
+            World(
+                id: $0.column("id")?.int32 ?? 0,
+                randomnumber: $0.column("randomnumber")?.int ?? 0
+            )
+        }
+    }.flatten(on: req.eventLoop)
+}
+
+try app.run()

+ 27 - 0
frameworks/Swift/vapor/vapor-sql-kit.dockerfile

@@ -0,0 +1,27 @@
+# ================================
+# Build image
+# ================================
+FROM vapor/swift:5.2 as build
+WORKDIR /build
+
+# Copy entire repo into container
+COPY ./vapor-sql-kit .
+
+# Compile with optimizations
+RUN swift build \
+	--enable-test-discovery \
+	-c release
+
+# ================================
+# Run image
+# ================================
+FROM vapor/ubuntu:18.04
+WORKDIR /run
+
+# Copy build artifacts
+COPY --from=build /build/.build/release /run
+
+# Copy Swift runtime libraries
+COPY --from=build /usr/lib/swift/ /usr/lib/swift/
+
+ENTRYPOINT ["./app", "serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]

+ 22 - 0
frameworks/Swift/vapor/vapor-sql-kit/Package.swift

@@ -0,0 +1,22 @@
+// swift-tools-version:5.1
+import PackageDescription
+
+let package = Package(
+    name: "vapor-sql-kit",
+    platforms: [
+        .macOS(.v10_15)
+    ],
+    products: [
+        .executable(name: "app", targets: ["App"])
+    ],
+    dependencies: [
+        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
+        .package(url: "https://github.com/vapor/postgres-kit.git", from: "2.0.0"),
+    ],
+    targets: [
+        .target(name: "App", dependencies: [
+            "PostgresKit",
+            "Vapor"
+        ], path: "Sources")
+    ]
+)

+ 25 - 0
frameworks/Swift/vapor/vapor-sql-kit/Sources/Utilities.swift

@@ -0,0 +1,25 @@
+import Vapor
+
+extension Int {
+    func bounded(to range: ClosedRange<Int>) -> Int {
+        switch self {
+        case ...range.lowerBound:
+            return range.lowerBound
+        case range.upperBound...:
+            return range.upperBound
+        default:
+            return self
+        }
+    }
+}
+
+extension System {
+    // tfb-server (aka, citrine) uses 28 hyper-threaded cores
+    // postgresql.conf specifies max_connections = 2000
+    //
+    // 2000 / (28 * 2) = 35.7 (theoretical max)
+    //
+    // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Environment#citrine-self-hosted
+    // https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/toolset/databases/postgres/postgresql.conf#L64
+    static var maxConnectionsPerEventLoop: Int { 32 }
+}

+ 6 - 0
frameworks/Swift/vapor/vapor-sql-kit/Sources/World.swift

@@ -0,0 +1,6 @@
+import Vapor
+
+struct World: Content {
+    var id: Int32?
+    var randomnumber: Int
+}

+ 57 - 0
frameworks/Swift/vapor/vapor-sql-kit/Sources/main.swift

@@ -0,0 +1,57 @@
+import PostgresKit
+import Vapor
+
+var env = try Environment.detect()
+try LoggingSystem.bootstrap(from: &env)
+
+let app = Application(env)
+defer { app.shutdown() }
+
+app.http.server.configuration.serverName = "Vapor"
+
+app.logger.notice("💧 VAPOR")
+app.logger.notice("System.coreCount: \(System.coreCount)")
+app.logger.notice("System.maxConnectionsPerEventLoop: \(System.maxConnectionsPerEventLoop)")
+
+let pools = EventLoopGroupConnectionPool(
+    source: PostgresConnectionSource(configuration: .init(
+        hostname: "tfb-database",
+        username: "benchmarkdbuser",
+        password: "benchmarkdbpass",
+        database: "hello_world"
+    )), 
+    maxConnectionsPerEventLoop: System.maxConnectionsPerEventLoop,
+    on: app.eventLoopGroup
+)
+
+extension Request {
+    func sql(_ pools: EventLoopGroupConnectionPool<PostgresConnectionSource>) -> SQLDatabase {
+        pools.pool(for: self.eventLoop).database(logger: self.logger).sql()
+    }
+}
+
+app.get("db") { req in
+    req.sql(pools).select()
+        .column("id")
+        .column("randomnumber")
+        .from("World")
+        .where("id", .equal, Int32.random(in: 1...10_000))
+        .first(decoding: World.self)
+        .unwrap(or: Abort(.notFound))
+}
+
+app.get("queries") { req -> EventLoopFuture<[World]> in
+    let queries = (req.query["queries"] ?? 1).bounded(to: 1...500)
+    let db = req.sql(pools)
+    return (0 ..< queries).map { _ -> EventLoopFuture<World> in
+        db.select()
+            .column("id")
+            .column("randomnumber")
+            .from("World")
+            .where("id", .equal, Int32.random(in: 1...10_000))
+            .first(decoding: World.self)
+            .unwrap(or: Abort(.notFound))
+    }.flatten(on: req.eventLoop)
+}
+
+try app.run()

+ 1 - 1
frameworks/Swift/vapor/vapor.dockerfile

@@ -5,7 +5,7 @@ FROM vapor/swift:5.2 as build
 WORKDIR /build
 
 # Copy entire repo into container
-COPY ./app .
+COPY ./vapor-default .
 
 # Compile with optimizations
 RUN swift build \