Skip to content

Commit

Permalink
[TT-13819] Benchmark updates, session limiter workaround for test gor…
Browse files Browse the repository at this point in the history
…outine leak (#6826)

### **PR Type**
Enhancement, Tests


___

### **Description**
- Added `DisableRateLimit` and `DisableQuota` flags in multiple test
cases.

- Improved benchmark scripts and added skipping for specific benchmarks.

- Refactored session limiter to encourage reuse of `bucketStore`.

- Updated CI benchmark script for better profiling and output.


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Tests</strong></td><td><details><summary>7
files</summary><table>
<tr>
<td><strong>api_definition_test.go</strong><dd><code>Added
<code>DisableRateLimit</code> and <code>DisableQuota</code> flags in API
definition tests</code></dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-2394daab6fdc5f8dc234699c80c0548947ee3d68d2e33858258d73a8b5eb6f44">+2/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>event_system_test.go</strong><dd><code>Added benchmark
skipping for generic event handlers</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-59fda3ebcb87e3c16f222e51988dfb18be9239c84caeef0137db04ffe9ab8f3c">+2/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>mw_basic_auth_test.go</strong><dd><code>Added
`DisableRateLimit` and `DisableQuota` flags in basic auth
tests</code></dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-148b4d4c5c77fa4382e83fd583c36d21bba7b52217f821095abbc517d277b16f">+2/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>mw_jwt_test.go</strong><dd><code>Added `DisableRateLimit`
and `DisableQuota` flags in JWT tests</code></dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-406bf8fdb6c0cc77f04c6245c70abfc592ddb1525aa843200d850e14d135ebfc">+10/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>mw_transform_test.go</strong><dd><code>Refactored transform
middleware benchmarks for better structure</code></dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-ec6f80b3dcb001b2a2ac9b7277fff606bd77d796f99b8c1d10b8d0d55863deb3">+9/-7</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>oauth_manager_test.go</strong><dd><code>Added benchmark
skipping for OAuth token purging</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-139c3beb238f234728bde9f619f501cf730a7e275d17c8511277272d1dcd6fc6">+2/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>

<td><strong>res_handler_header_injector_test.go</strong><dd><code>Adjusted
header injection benchmarks and test cases</code>&nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-1c82da1ac85593e31ce947ef821703967ceb8065a5434c6749b802a1b93f9117">+7/-6</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

</table></details></td></tr><tr><td><strong>Enhancement</strong></td><td><details><summary>2
files</summary><table>
<tr>
<td><strong>session_manager.go</strong><dd><code>Refactored session
limiter to reuse `bucketStore`</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-e6b40a285464cd86736e970c4c0b320b44c75b18b363d38c200e9a9d36cdabb6">+4/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>ci-benchmark.sh</strong><dd><code>Enhanced CI benchmark
script with profiling and output improvements</code></dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-e789974499a5ba77194df612e751bc3db20b73c389466c679e4e74521199dd48">+9/-3</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></details></td></tr><tr><td><strong>Configuration
changes</strong></td><td><details><summary>1 files</summary><table>
<tr>
<td><strong>CODEOWNERS</strong><dd><code>Updated ownership for `/bin/`
directory</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/TykTechnologies/tyk/pull/6826/files#diff-3d36a1bf06148bc6ba1ce2ed3d19de32ea708d955fed212c0d27c536f0bd4da7">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></details></td></tr></tr></tbody></table>

___

> 💡 **PR-Agent usage**: Comment `/help "your question"` on any pull
request to receive relevant information

---------

Co-authored-by: Tit Petric <tit@tyk.io>
  • Loading branch information
titpetric and Tit Petric authored Jan 15, 2025
1 parent 421f64f commit 155e11b
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 44 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

# Core API Squad ownership of CI test pipeline and developer tooling.

/bin/ @TykTechnologies/core-api-squad
.github/workflows/ci-tests.yml @TykTechnologies/core-api-squad
.github/workflows/release-tests.yml @TykTechnologies/core-api-squad
/.taskfiles/ @TykTechnologies/core-api-squad
Expand Down
16 changes: 13 additions & 3 deletions bin/ci-benchmark.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
#!/bin/bash

set -e

benchRegex=${1:-.}
# Build gw test binary
go test -o gateway.test -c ./gateway

BENCHMARKS=$(./gateway.test -test.list=Bench.+)

TYK_LOGLEVEL= go test -run=NONE -bench=$benchRegex || fatal "go test -run=NONE -bench=$benchRegex"
for benchmark in $BENCHMARKS; do
echo $benchmark
benchRegex="^${benchmark}$"
./gateway.test -test.run=^$ -test.bench=$benchRegex -test.count=1 \
-test.benchtime 30s -test.benchmem \
-test.cpuprofile=coverage/$benchmark-cpu.out \
-test.memprofile=coverage/$benchmark-mem.out \
-test.trace=coverage/$benchmark-trace.out
done
2 changes: 2 additions & 0 deletions gateway/api_definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,8 @@ func (ts *Test) testPrepareDefaultVersion() (string, *APISpec) {
spec.Proxy.ListenPath = "/"

spec.UseKeylessAccess = false
spec.DisableRateLimit = true
spec.DisableQuota = true
})[0]

return CreateSession(ts.Gw, func(s *user.SessionState) {
Expand Down
2 changes: 2 additions & 0 deletions gateway/event_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ func TestInitGenericEventHandlers(t *testing.T) {
}

func BenchmarkInitGenericEventHandlers(b *testing.B) {
b.Skip()

ts := StartTest(nil)
defer ts.Close()

Expand Down
3 changes: 2 additions & 1 deletion gateway/mw_basic_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ func genAuthHeader(username, password string) string {
}

func (ts *Test) testPrepareBasicAuth(cacheDisabled bool) *user.SessionState {

session := CreateStandardSession()
session.BasicAuthData.Password = "password"
session.AccessRights = map[string]user.AccessDefinition{"test": {APIID: "test", Versions: []string{"v1"}}}
Expand All @@ -33,6 +32,8 @@ func (ts *Test) testPrepareBasicAuth(cacheDisabled bool) *user.SessionState {
spec.UseKeylessAccess = false
spec.Proxy.ListenPath = "/"
spec.OrgID = "default"
spec.DisableRateLimit = true
spec.DisableQuota = true
})

return session
Expand Down
10 changes: 10 additions & 0 deletions gateway/mw_jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ func (ts *Test) prepareGenericJWTSession(testName string, method string, claimNa
spec.EnableJWT = true
spec.Proxy.ListenPath = "/"
spec.JWTSkipKid = ApiSkipKid
spec.DisableRateLimit = true
spec.DisableQuota = true

if claimName != KID {
spec.JWTIdentityBaseField = claimName
Expand Down Expand Up @@ -471,6 +473,8 @@ func (ts *Test) prepareJWTSessionRSAWithRawSourceOnWithClientID(isBench bool) st
spec.JWTIdentityBaseField = "user_id"
spec.JWTClientIDBaseField = "azp"
spec.Proxy.ListenPath = "/"
spec.DisableRateLimit = true
spec.DisableQuota = true
})[0]

policyID := ts.CreatePolicy(func(p *user.Policy) {
Expand Down Expand Up @@ -552,6 +556,8 @@ func (ts *Test) prepareJWTSessionRSAWithRawSource() string {
spec.JWTIdentityBaseField = "user_id"
spec.JWTPolicyFieldName = "policy_id"
spec.Proxy.ListenPath = "/"
spec.DisableRateLimit = true
spec.DisableQuota = true
})

pID := ts.CreatePolicy(func(p *user.Policy) {
Expand Down Expand Up @@ -1511,6 +1517,8 @@ func (ts *Test) prepareJWTSessionRSAWithJWK() string {
spec.JWTIdentityBaseField = "user_id"
spec.JWTPolicyFieldName = "policy_id"
spec.Proxy.ListenPath = "/"
spec.DisableRateLimit = true
spec.DisableQuota = true
})

pID := ts.CreatePolicy(func(p *user.Policy) {
Expand Down Expand Up @@ -1579,6 +1587,8 @@ func (ts *Test) prepareJWTSessionRSAWithEncodedJWK() (*APISpec, string) {
spec.JWTIdentityBaseField = "user_id"
spec.JWTPolicyFieldName = "policy_id"
spec.Proxy.ListenPath = "/"
spec.DisableRateLimit = true
spec.DisableQuota = true
})[0]

pID := ts.CreatePolicy(func(p *user.Policy) {
Expand Down
67 changes: 34 additions & 33 deletions gateway/mw_transform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ func TestTransformNonAscii(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()

ad := apidef.APIDefinition{}
spec := APISpec{APIDefinition: &ad}
spec.EnableContextVars = false
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := TransformMiddleware{base}

if err := transformBody(r, tmeta, &transform); err != nil {
Expand All @@ -64,15 +63,16 @@ func BenchmarkTransformNonAscii(b *testing.B) {
ts := StartTest(nil)
defer ts.Close()

spec := APISpec{}
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
transform := TransformMiddleware{base}
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := &TransformMiddleware{base}

for i := 0; i < b.N; i++ {
r := TestReq(b, "GET", "/", in)

if err := transformBody(r, tmeta, &transform); err != nil {
if err := transformBody(r, tmeta, transform); err != nil {
b.Fatalf("wanted nil error, got %v", err)
}
}
Expand All @@ -90,10 +90,10 @@ func TestTransformXMLCrash(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()

ad := apidef.APIDefinition{}
spec := APISpec{APIDefinition: &ad}
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := TransformMiddleware{base}

if err := transformBody(r, tmeta, &transform); err == nil {
Expand Down Expand Up @@ -145,10 +145,10 @@ func TestTransformJSONMarshalXMLInput(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()

ad := apidef.APIDefinition{}
spec := APISpec{APIDefinition: &ad}
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := TransformMiddleware{base}

if err := transformBody(r, tmeta, &transform); err != nil {
Expand All @@ -172,10 +172,10 @@ func TestTransformJSONMarshalJSONInput(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()

ad := apidef.APIDefinition{}
spec := APISpec{APIDefinition: &ad}
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := TransformMiddleware{base}

if err := transformBody(r, tmeta, &transform); err != nil {
Expand Down Expand Up @@ -211,10 +211,10 @@ func TestTransformJSONMarshalJSONArrayInput(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()

ad := apidef.APIDefinition{}
spec := APISpec{APIDefinition: &ad}
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := TransformMiddleware{base}

if err := transformBody(r, tmeta, &transform); err != nil {
Expand All @@ -236,9 +236,10 @@ func BenchmarkTransformJSONMarshal(b *testing.B) {
ts := StartTest(nil)
defer ts.Close()

spec := APISpec{}
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := TransformMiddleware{base}

for i := 0; i < b.N; i++ {
Expand All @@ -258,10 +259,10 @@ func TestTransformXMLMarshal(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()

ad := apidef.APIDefinition{}
spec := APISpec{APIDefinition: &ad}
base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw}
base.Spec.EnableContextVars = false
ad := &apidef.APIDefinition{}
spec := &APISpec{APIDefinition: ad}
base := &BaseMiddleware{Spec: spec, Gw: ts.Gw}

transform := TransformMiddleware{base}

if err := transformBody(r, tmeta, &transform); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions gateway/mw_version_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func (ts *Test) testPrepareVersioning() (string, string) {
spec.VersionDefinition.Location = "header"
spec.VersionDefinition.Key = "version"
spec.Proxy.ListenPath = "/"
spec.DisableRateLimit = true
spec.DisableQuota = true
spec.VersionData.Versions["expired"] = apidef.VersionInfo{
Name: "expired",
Expires: "2006-01-02 15:04",
Expand Down
2 changes: 2 additions & 0 deletions gateway/oauth_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,8 @@ func TestPurgeOAuthClientTokens(t *testing.T) {
}

func BenchmarkPurgeLapsedOAuthTokens(b *testing.B) {
b.Skip()

conf := func(globalConf *config.Config) {
// set tokens to be expired after 1 second
globalConf.OauthTokenExpire = 1
Expand Down
13 changes: 7 additions & 6 deletions gateway/res_handler_header_injector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func testPrepareResponseHeaderInjection(ts *Test) {
spec.UseKeylessAccess = true
spec.Proxy.ListenPath = "/"
spec.OrgID = "default"
spec.DisableRateLimit = true
spec.DisableQuota = true
UpdateAPIVersion(spec, "v1", func(v *apidef.VersionInfo) {
v.UseExtendedPaths = true
json.Unmarshal([]byte(`[
Expand Down Expand Up @@ -136,10 +138,6 @@ func BenchmarkResponseHeaderInjection(b *testing.B) {
}

deleteHeaders := map[string]string{
"X-Tyk-Test": "1",
cachedResponseHeader: "1",
}
deleteHeadersCached := map[string]string{
"X-Tyk-Test": "1",
}

Expand All @@ -151,9 +149,12 @@ func BenchmarkResponseHeaderInjection(b *testing.B) {
{Method: "GET", Path: "/test-with-slash", HeadersMatch: addHeaders, HeadersNotMatch: deleteHeaders},
{Method: "GET", Path: "/test-no-slash", HeadersMatch: addHeaders, HeadersNotMatch: deleteHeaders},
{Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeaders, HeadersNotMatch: deleteHeaders, BodyMatch: `"Url":"/newpath"`},
{Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeadersCached, BodyMatch: `"X-I-Am":"Request"`},
{Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeadersCached, BodyMatch: userAgent},
{Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeaders, BodyMatch: `"X-I-Am":"Request"`},
{Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeaders, BodyMatch: userAgent},
}...)

// It's a loop, first time won't be cached.
addHeaders[cachedResponseHeader] = "1"
}
}

Expand Down
5 changes: 4 additions & 1 deletion gateway/session_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ type SessionLimiter struct {
smoothing *rate.Smoothing
}

// Encourage reuse in NewSessionLimiter.
var sessionLimiterBucketStore = memorycache.New()

// NewSessionLimiter initializes the session limiter.
//
// The session limiter initializes the storage required for rate limiters.
Expand All @@ -70,7 +73,7 @@ func NewSessionLimiter(ctx context.Context, conf *config.Config, drlManager *drl
ctx: ctx,
drlManager: drlManager,
config: conf,
bucketStore: memorycache.New(),
bucketStore: sessionLimiterBucketStore,
}

log.Infof("[RATELIMIT] %s", conf.RateLimit.String())
Expand Down

0 comments on commit 155e11b

Please sign in to comment.