-
Notifications
You must be signed in to change notification settings - Fork 423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance tests part 1 #3434
Merged
Merged
Performance tests part 1 #3434
Changes from 47 commits
Commits
Show all changes
60 commits
Select commit
Hold shift + click to select a range
767d9c2
wip
kciesielski 1998a34
Dynamic perf test runner
kciesielski 32ba29e
Merge branch 'master' into perf-tests-2023
kciesielski f2c5d79
Restore netty server dependency
kciesielski 7347583
Remove unneeded files
kciesielski 67973b1
Remove unneded build utils
kciesielski 917dfeb
Apply base simulation to all sims
kciesielski 4695510
Remove old way of running perf tests
kciesielski 7f8110b
Fix file size to 5MB
kciesielski 4342d97
Explain why a command is used
kciesielski 6a9bc15
Parameterize active user count
kciesielski 5bcc177
Switch from Akka to Pekko
kciesielski fc414b2
Add Netty Cats server
kciesielski 881f2c3
Add Play server
kciesielski 01536c0
Merge branch 'master' into perf-tests-2023
kciesielski 5ec7484
Vanilla Play server skeleton
kciesielski 987ccd1
Finish Play
kciesielski dc71db9
Refator vanilla Play
kciesielski 01f91bc
Use new ActorSystem for each Pekko/Play server run
kciesielski 2aa228a
Initial suite runner and log processor
kciesielski eda178b
Save HTML report
kciesielski 13291a0
CSV reported and inmprovements to HTML reporter
kciesielski 50a191d
Ensure same filename for all reports
kciesielski 1449769
Allow running all servers or all simulations with '*'
kciesielski 9f44abf
Parse arguments
kciesielski 55d3daa
Remove sbt command
kciesielski 97093a2
Tweak HTML report style
kciesielski 3fbe5a5
Allow skipping Gatling reports
kciesielski cfd243c
Add Vert.x Tapir server
kciesielski d677a0e
Skip duplicates
kciesielski 4311fb6
Finish Vertx vanilla server
kciesielski 73e0506
Display servers as rows in HTML
kciesielski 3b0969c
Disable Gatling reports by defaults, improve flag
kciesielski af44696
Add missing endpoints to http4s Vanilla
kciesielski 42df183
Add missing vanilla endpoints for Pekko
kciesielski 90fe6e6
Refactoring and cleanup
kciesielski a5146c0
Fix netty-cats server shutdown
kciesielski 3ffd82e
Use constant
kciesielski 0b86d1d
Merge branch 'master' into perf-tests-2023
kciesielski 8732f0d
Minor tweaks in Vertx vanilla file endpoint
kciesielski 33763ee
Use text/plain because otherwise Play complains
kciesielski 3505216
Sort rows in HTML report
kciesielski 5fa603f
Fixes
kciesielski f303791
Add Vertx Cats Effect server
kciesielski 1bfc354
Many improvements
kciesielski 0188b7b
Fix warmup
kciesielski ce012a2
Merge branch 'master' into perf-tests-2023
kciesielski 818c953
Include warmup in total duration estimations
kciesielski a4ceeb9
Restore
kciesielski cb814cb
Display default values of optional parameters
kciesielski f8dbbc1
Disable logging
kciesielski 1bf6442
List available servers and sims in the help view
kciesielski 76a5e4b
Documentation
kciesielski c40e455
Merge branch 'master' into perf-tests-2023
kciesielski 6aca7f8
Merge branch 'master' into perf-tests-2023
kciesielski bc9bad5
Merge remote-tracking branch 'origin/perf-tests-2023' into perf-tests…
kciesielski 6afe52f
Remove accidental double release after merge
kciesielski f0f9f85
Less personal example ;)
kciesielski 18c11df
Restore ideSkipProject
kciesielski 8904ef2
Add warmup to the info screen
kciesielski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,15 @@ | ||
package sttp.tapir.perf | ||
|
||
import sttp.tapir.{PublicEndpoint, endpoint, path, stringBody} | ||
|
||
import scala.io.StdIn | ||
import java.io.File | ||
import java.nio.file.Path | ||
import java.util.Date | ||
import scala.util.Random | ||
|
||
object Common { | ||
def genTapirEndpoint(n: Int): PublicEndpoint[Int, String, String, Any] = endpoint.get | ||
.in("path" + n.toString) | ||
.in(path[Int]("id")) | ||
.errorOut(stringBody) | ||
.out(stringBody) | ||
val rootPackage = "sttp.tapir.perf" | ||
val LargeInputSize = 5 * 1024 * 1024 | ||
val Port = 8080 | ||
val TmpDir: File = new java.io.File(System.getProperty("java.io.tmpdir")).getAbsoluteFile | ||
def tempFilePath(): Path = TmpDir.toPath.resolve(s"tapir-${new Date().getTime}-${Random.nextLong()}") | ||
|
||
def blockServer(): Unit = { | ||
println(Console.BLUE + "Server now online. Please navigate to http://localhost:8080/path0/1\nPress RETURN to stop..." + Console.RESET) | ||
StdIn.readLine() | ||
println("Server terminated") | ||
} | ||
} |
55 changes: 0 additions & 55 deletions
55
perf-tests/src/main/scala/sttp/tapir/perf/akka/AkkaHttp.scala
This file was deleted.
Oops, something went wrong.
67 changes: 67 additions & 0 deletions
67
perf-tests/src/main/scala/sttp/tapir/perf/apis/Endpoints.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package sttp.tapir.perf.apis | ||
|
||
import cats.effect.IO | ||
import sttp.tapir._ | ||
import sttp.tapir.perf.Common._ | ||
import sttp.tapir.server.ServerEndpoint | ||
import sttp.tapir.server.model.EndpointExtensions._ | ||
|
||
import java.io.File | ||
import scala.concurrent.Future | ||
|
||
trait Endpoints { | ||
type EndpointGen = Int => PublicEndpoint[_, String, String, Any] | ||
type ServerEndpointGen[F[_]] = Int => ServerEndpoint[Any, F] | ||
|
||
def serverEndpoints[F[_]](reply: String => F[String]): List[ServerEndpointGen[F]] = { | ||
List( | ||
{ (n: Int) => | ||
endpoint.get | ||
.in("path" + n.toString) | ||
.in(path[Int]("id")) | ||
.out(stringBody) | ||
.serverLogicSuccess { id => | ||
reply((id + n).toString) | ||
} | ||
}, | ||
{ (n: Int) => | ||
endpoint.post | ||
.in("path" + n.toString) | ||
.in(stringBody) | ||
.maxRequestBodyLength(LargeInputSize + 1024L) | ||
.out(stringBody) | ||
.serverLogicSuccess { | ||
body: String => | ||
reply(s"Ok [$n], string length = ${body.length}") | ||
} | ||
}, | ||
{ (n: Int) => | ||
endpoint.post | ||
.in("pathBytes" + n.toString) | ||
.in(byteArrayBody) | ||
.maxRequestBodyLength(LargeInputSize + 1024L) | ||
.out(stringBody) | ||
.serverLogicSuccess { body: Array[Byte] => | ||
reply(s"Ok [$n], bytes length = ${body.length}") | ||
} | ||
}, | ||
{ (n: Int) => | ||
endpoint.post | ||
.in("pathFile" + n.toString) | ||
.in(fileBody) | ||
.maxRequestBodyLength(LargeInputSize + 1024L) | ||
.out(stringBody) | ||
.serverLogicSuccess { | ||
body: File => | ||
reply(s"Ok [$n], file saved to ${body.toPath}") | ||
} | ||
} | ||
) | ||
} | ||
|
||
def genServerEndpoints[F[_]](routeCount: Int)(reply: String => F[String]): List[ServerEndpoint[Any, F]] = | ||
serverEndpoints[F](reply).flatMap(gen => (0 to routeCount).map(i => gen(i))) | ||
|
||
def genEndpointsFuture(count: Int): List[ServerEndpoint[Any, Future]] = genServerEndpoints(count)(Future.successful) | ||
def genEndpointsIO(count: Int): List[ServerEndpoint[Any, IO]] = genServerEndpoints(count)(IO.pure) | ||
} |
11 changes: 11 additions & 0 deletions
11
perf-tests/src/main/scala/sttp/tapir/perf/apis/ServerRunner.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package sttp.tapir.perf.apis | ||
|
||
import cats.effect.IO | ||
|
||
trait ServerRunner { | ||
def start: IO[ServerRunner.KillSwitch] | ||
} | ||
|
||
object ServerRunner { | ||
type KillSwitch = IO[Unit] | ||
} |
63 changes: 43 additions & 20 deletions
63
perf-tests/src/main/scala/sttp/tapir/perf/http4s/Http4s.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,77 @@ | ||
package sttp.tapir.perf.http4s | ||
|
||
import cats.effect._ | ||
import cats.effect.unsafe.implicits.global | ||
import cats.syntax.all._ | ||
import fs2.io.file.{Files, Path => Fs2Path} | ||
import org.http4s._ | ||
import org.http4s.blaze.server.BlazeServerBuilder | ||
import org.http4s.dsl._ | ||
import org.http4s.implicits._ | ||
import org.http4s.server.Router | ||
import sttp.tapir.perf | ||
import sttp.tapir.perf.Common | ||
import sttp.monad.MonadError | ||
import sttp.tapir.integ.cats.effect.CatsMonadError | ||
import sttp.tapir.perf.Common._ | ||
import sttp.tapir.perf.apis._ | ||
import sttp.tapir.server.http4s.Http4sServerInterpreter | ||
|
||
object Vanilla { | ||
val router: Int => HttpRoutes[IO] = (nRoutes: Int) => | ||
Router( | ||
(0 to nRoutes).map((n: Int) => | ||
("/path" + n.toString) -> { | ||
("/") -> { | ||
val dsl = Http4sDsl[IO] | ||
import dsl._ | ||
HttpRoutes.of[IO] { case GET -> Root / IntVar(id) => | ||
Ok((id + n).toString) | ||
HttpRoutes.of[IO] { | ||
case GET -> Root / s"path$n" / IntVar(id) => | ||
Ok((id + n.toInt).toString) | ||
case req @ POST -> Root / s"path$n" => | ||
req.as[String].flatMap { str => | ||
Ok(s"Ok [$n], string length = ${str.length}") | ||
} | ||
case req @ POST -> Root / s"pathBytes$n" => | ||
req.as[Array[Byte]].flatMap { bytes => | ||
Ok(s"Ok [$n], bytes length = ${bytes.length}") | ||
} | ||
case req @ POST -> Root / s"pathFile$n" => | ||
val filePath = tempFilePath() | ||
val sink = Files[IO].writeAll(Fs2Path.fromNioPath(filePath)) | ||
req.body | ||
.through(sink) | ||
.compile | ||
.drain | ||
.flatMap(_ => Ok(s"Ok [$n], file saved to ${filePath.toAbsolutePath.toString}")) | ||
} | ||
} | ||
): _* | ||
) | ||
} | ||
|
||
object Tapir { | ||
object Tapir extends Endpoints { | ||
|
||
implicit val mErr: MonadError[IO] = new CatsMonadError[IO] | ||
|
||
|
||
val router: Int => HttpRoutes[IO] = (nRoutes: Int) => | ||
Router("/" -> { | ||
Http4sServerInterpreter[IO]().toRoutes( | ||
(0 to nRoutes) | ||
.map((n: Int) => Common.genTapirEndpoint(n).serverLogic(id => IO(((id + n).toString).asRight[String]))) | ||
.toList | ||
genEndpointsIO(nRoutes) | ||
) | ||
}) | ||
} | ||
|
||
object Http4s { | ||
def runServer(router: HttpRoutes[IO]): IO[ExitCode] = { | ||
object server { | ||
def runServer(router: HttpRoutes[IO]): IO[ServerRunner.KillSwitch] = | ||
BlazeServerBuilder[IO] | ||
.bindHttp(8080, "localhost") | ||
.bindHttp(Port, "localhost") | ||
.withHttpApp(router.orNotFound) | ||
.resource | ||
.use(_ => { perf.Common.blockServer(); IO.pure(ExitCode.Success) }) | ||
} | ||
.allocated | ||
.map(_._2) | ||
.map(_.flatTap { _ => | ||
IO.println("Http4s server closed.") | ||
}) | ||
} | ||
|
||
object TapirServer extends App { Http4s.runServer(Tapir.router(1)).unsafeRunSync() } | ||
object TapirMultiServer extends App { Http4s.runServer(Tapir.router(128)).unsafeRunSync() } | ||
object VanillaServer extends App { Http4s.runServer(Vanilla.router(1)).unsafeRunSync() } | ||
object VanillaMultiServer extends App { Http4s.runServer(Vanilla.router(128)).unsafeRunSync() } | ||
object TapirServer extends ServerRunner { override def start = server.runServer(Tapir.router(1)) } | ||
object TapirMultiServer extends ServerRunner { override def start = server.runServer(Tapir.router(128)) } | ||
object VanillaServer extends ServerRunner { override def start = server.runServer(Vanilla.router(1)) } | ||
object VanillaMultiServer extends ServerRunner { override def start = server.runServer(Vanilla.router(128)) } |
35 changes: 35 additions & 0 deletions
35
perf-tests/src/main/scala/sttp/tapir/perf/netty/cats/NettyCats.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package sttp.tapir.perf.netty.cats | ||
|
||
import cats.effect.IO | ||
import cats.effect.kernel.Resource | ||
import sttp.tapir.perf.Common._ | ||
import sttp.tapir.perf.apis._ | ||
import sttp.tapir.server.ServerEndpoint | ||
import sttp.tapir.server.netty.cats.NettyCatsServer | ||
|
||
object Tapir extends Endpoints | ||
|
||
object NettyCats { | ||
|
||
def runServer(endpoints: List[ServerEndpoint[Any, IO]]): IO[ServerRunner.KillSwitch] = { | ||
val declaredPort = Port | ||
val declaredHost = "0.0.0.0" | ||
// Starting netty server | ||
NettyCatsServer | ||
.io() | ||
.flatMap { server => | ||
Resource.make( | ||
server | ||
.port(declaredPort) | ||
.host(declaredHost) | ||
.addEndpoints(endpoints) | ||
.start() | ||
)(binding => binding.stop()) | ||
} | ||
.allocated | ||
.map(_._2) | ||
} | ||
} | ||
|
||
object TapirServer extends ServerRunner { override def start = NettyCats.runServer(Tapir.genEndpointsIO(1)) } | ||
object TapirMultiServer extends ServerRunner { override def start = NettyCats.runServer(Tapir.genEndpointsIO(128)) } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's a path to a new temp file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'll rename this function to make it clearer.