Skip to content

Commit

Permalink
add benchmarks for PathMatcher performance
Browse files Browse the repository at this point in the history
Added a JMH benchmark suite to evaluate the performance of the `PathMatcher` implementation against a simple `Set`-based matcher.

Changes:
- Created `PathMatcherBenchmark` in `/benchmarks/src/main/scala/zio/http/gen/routing/PathMatcherBenchmark.scala`.
- Benchmarked two matching strategies:
  1. `Set[String]`-based matcher.
  2. `PathMatcher` state machine-based matcher.
- Configured benchmarks to measure:
  - Execution time in nanoseconds.
  - Different path counts (10, 100, 1000).
  - Both matching and non-matching paths.
- Utilized randomized path generation for diverse test cases:
  - Included paths with varying depths and alphanumeric components.
  - Mixed matched and unmatched paths for realistic testing.
- Configured JMH annotations for warmup, measurement, and iterations:
  - Warmup: 5 iterations of 1 second each.
  - Measurement: 5 iterations of 1 second each.
  - Single fork to ensure reproducibility.

This update provides performance insights into `PathMatcher`, aiding in optimization and scalability analysis.
  • Loading branch information
hoklims authored Nov 23, 2024
1 parent 0218a49 commit 9740604
Showing 1 changed file with 57 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package zio.http.gen.routing

import org.openjdk.jmh.annotations._
import java.util.concurrent.TimeUnit
import scala.util.Random

@State(Scope.Thread)
@BenchmarkMode(Array(Mode.AverageTime))
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
class PathMatcherBenchmark {

@Param(Array("10", "100", "1000"))
var pathCount: Int = _

var setMatcher: Set[String] = _
var stateMatcher: PathMatcher = _
var testPaths: Array[String] = _

@Setup
def setup(): Unit = {
val paths = (1 to pathCount).map { i =>
val depth = 1 + Random.nextInt(4)
(0 until depth)
.map(_ => Random.alphanumeric.take(5).mkString)
.mkString("/", "/", "")
}.toSet

setMatcher = paths
stateMatcher = PathMatcher.compile(paths)

testPaths = (
paths.take(pathCount / 2).toArray ++
Array.fill(pathCount / 2)(s"/nonexistent/${Random.nextInt()}")
)
}

@Benchmark
def benchmarkSetMatcher(): Int = {
var count = 0
testPaths.foreach { path =>
if (setMatcher.contains(path)) count += 1
}
count
}

@Benchmark
def benchmarkStateMatcher(): Int = {
var count = 0
testPaths.foreach { path =>
if (stateMatcher.matches(path)) count += 1
}
count
}
}

0 comments on commit 9740604

Please sign in to comment.