Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
finagle-http: improve performance of StatsFilter
Problem The `c.t.f.http.filters.StatsFilter` manages metrics by converting the response status code to a String on every invocation. There is no need for doing this on every call. Solution Keep references to valid HTTP status code ranges, where they can be referenced by the status code's Int value, without allocating a new String on each request. Also change the memoization of a specific status code to be based off of the Int value. Additionally, the allocation of a `Duration` is removed by changing how the elapsed time in milliseconds is determined. JIRA Issues: CSL-8375 Differential Revision: https://phabricator.twitter.biz/D350733
- Loading branch information
Showing
4 changed files
with
141 additions
and
18 deletions.
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
57 changes: 57 additions & 0 deletions
57
finagle-benchmark/src/main/scala/com/twitter/finagle/filter/HttpStatsFilterBenchmark.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,57 @@ | ||
package com.twitter.finagle.filter | ||
|
||
import com.twitter.finagle.Service | ||
import com.twitter.finagle.benchmark.StdBenchAnnotations | ||
import com.twitter.finagle.http.{Request, Response, Status} | ||
import com.twitter.finagle.http.filter.StatsFilter | ||
import com.twitter.finagle.stats.NullStatsReceiver | ||
import com.twitter.util.{Await, Future} | ||
import org.openjdk.jmh.annotations.{Benchmark, Scope, State} | ||
import scala.util.Random | ||
|
||
// ./sbt 'project finagle-benchmark' 'jmh:run HttpStatsFilterBenchmark' | ||
@State(Scope.Benchmark) | ||
class HttpStatsFilterBenchmark extends StdBenchAnnotations { | ||
|
||
private[this] val request: Request = Request("/ping") | ||
|
||
private[this] val constResult: Future[Response] = Future.value { | ||
val rep = Response() | ||
rep.contentString = "pong" | ||
rep | ||
} | ||
|
||
private[this] val filter = new StatsFilter[Request]( | ||
NullStatsReceiver | ||
) | ||
|
||
val statusCodes = Array( | ||
Status.Accepted, | ||
Status.BadRequest, | ||
Status.Continue, | ||
Status.EnhanceYourCalm, | ||
Status.Forbidden, | ||
Status.NoContent, | ||
Status.Ok, | ||
Status.InternalServerError | ||
) | ||
|
||
private[this] val constSvc = filter.andThen(Service.constant[Response](constResult)) | ||
private[this] val randSvc = filter.andThen(Service.mk[Request, Response](_ => | ||
Future.value { | ||
Response(statusCodes(Random.nextInt(statusCodes.size))) | ||
})) | ||
|
||
@Benchmark | ||
def constantStatusCode(): Response = { | ||
val res = constSvc(request) | ||
Await.result(res) | ||
} | ||
|
||
@Benchmark | ||
def randomStatusCode(): Response = { | ||
val res = randSvc(request) | ||
Await.result(res) | ||
} | ||
|
||
} |
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