1// Copyright 2018 Istio Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package perftests 16 17import ( 18 "testing" 19 20 istio_mixer_v1 "istio.io/api/mixer/v1" 21 "istio.io/istio/mixer/pkg/perf" 22 spyadapter "istio.io/istio/mixer/test/spyAdapter" 23) 24 25// Tests single quota call into Mixer that dispatches instances to multiple noop inproc adapters. 26func Benchmark_Quota_1Client_1Call(b *testing.B) { 27 settings, spyAdapter := settingsWithAdapterAndTmpls() 28 settings.RunMode = perf.InProcess 29 30 setup := perf.Setup{ 31 Config: perf.Config{ 32 Global: mixerGlobalCfg, 33 Service: quotaInstToSpyAdapter + attrGenToSpyAdapter, 34 }, 35 36 Loads: []perf.Load{{ 37 Multiplier: 1, 38 Requests: []perf.Request{ 39 perf.BuildBasicCheck( 40 baseAttr, 41 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 42 "requestcount": {Amount: 1}, 43 }), 44 }, 45 }}, 46 } 47 48 perf.Run(b, &setup, settings) 49 validateQuotaBehavior(spyAdapter, b) 50} 51 52// Tests 5 synchronous identical quota call into Mixer that dispatches instances to multiple noop inproc adapters. 53func Benchmark_Quota_1Client_5SameCalls(b *testing.B) { 54 settings, spyAdapter := settingsWithAdapterAndTmpls() 55 settings.RunMode = perf.InProcess 56 57 setup := perf.Setup{ 58 Config: perf.Config{ 59 Global: mixerGlobalCfg, 60 Service: quotaInstToSpyAdapter + attrGenToSpyAdapter, 61 }, 62 63 Loads: []perf.Load{{ 64 Multiplier: 5, 65 Requests: []perf.Request{ 66 perf.BuildBasicCheck( 67 baseAttr, 68 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 69 "requestcount": {Amount: 1}, 70 }), 71 }, 72 }}, 73 } 74 75 perf.Run(b, &setup, settings) 76 validateQuotaBehavior(spyAdapter, b) 77} 78 79// Tests 5 synchronous different quota call into Mixer that dispatches instances to multiple noop inproc adapters. 80func Benchmark_Quota_1Client_5DifferentCalls(b *testing.B) { 81 settings, spyAdapter := settingsWithAdapterAndTmpls() 82 settings.RunMode = perf.InProcess 83 84 setup := perf.Setup{ 85 Config: perf.Config{ 86 Global: mixerGlobalCfg, 87 Service: quotaInstToSpyAdapter + attrGenToSpyAdapter, 88 }, 89 90 Loads: []perf.Load{ 91 { 92 Multiplier: 1, 93 Requests: []perf.Request{ 94 perf.BuildBasicCheck( 95 attr1, 96 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 97 "requestcount": {Amount: 1}, 98 }), 99 perf.BuildBasicCheck( 100 attr2, 101 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 102 "requestcount": {Amount: 1}, 103 }), 104 perf.BuildBasicCheck( 105 attr3, 106 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 107 "requestcount": {Amount: 1}, 108 }), 109 perf.BuildBasicCheck( 110 attr4, 111 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 112 "requestcount": {Amount: 1}, 113 }), 114 perf.BuildBasicCheck( 115 attr5, 116 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 117 "requestcount": {Amount: 1}, 118 }), 119 }, 120 }, 121 }, 122 } 123 124 perf.Run(b, &setup, settings) 125 validateQuotaBehavior(spyAdapter, b) 126} 127 128// Tests 4 async client, each sending 5 identical quota call into Mixer that dispatches instances to 129// multiple noop inproc adapters. 130func Benchmark_Quota_4Clients_5SameCallsEach(b *testing.B) { 131 settings, spyAdapter := settingsWithAdapterAndTmpls() 132 settings.RunMode = perf.InProcess 133 setup := perf.Setup{ 134 Config: perf.Config{ 135 Global: mixerGlobalCfg, 136 Service: quotaInstToSpyAdapter + attrGenToSpyAdapter, 137 }, 138 139 Loads: []perf.Load{ 140 { 141 Multiplier: 5, 142 Requests: []perf.Request{ 143 perf.BuildBasicCheck( 144 baseAttr, 145 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 146 "requestcount": {Amount: 1}, 147 }), 148 }, 149 }, 150 { 151 Multiplier: 5, 152 Requests: []perf.Request{ 153 perf.BuildBasicCheck( 154 baseAttr, 155 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 156 "requestcount": {Amount: 1}, 157 }), 158 }, 159 }, 160 { 161 Multiplier: 5, 162 Requests: []perf.Request{ 163 perf.BuildBasicCheck( 164 baseAttr, 165 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 166 "requestcount": {Amount: 1}, 167 }), 168 }, 169 }, 170 { 171 Multiplier: 5, 172 Requests: []perf.Request{ 173 perf.BuildBasicCheck( 174 baseAttr, 175 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 176 "requestcount": {Amount: 1}, 177 }), 178 }, 179 }, 180 }, 181 } 182 183 perf.Run(b, &setup, settings) 184 validateQuotaBehavior(spyAdapter, b) 185} 186 187// Tests 4 async client, each sending 5 different quota call into Mixer that dispatches instances to 188// multiple noop inproc adapters. 189func Benchmark_Quota_4Clients_5DifferentCallsEach(b *testing.B) { 190 settings, spyAdapter := settingsWithAdapterAndTmpls() 191 settings.RunMode = perf.InProcess 192 setup := perf.Setup{ 193 Config: perf.Config{ 194 Global: mixerGlobalCfg, 195 Service: quotaInstToSpyAdapter + attrGenToSpyAdapter, 196 }, 197 198 Loads: []perf.Load{ 199 { 200 Multiplier: 1, 201 Requests: []perf.Request{ 202 perf.BuildBasicCheck( 203 attr1, 204 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 205 "requestcount": {Amount: 1}, 206 }), 207 perf.BuildBasicCheck( 208 attr2, 209 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 210 "requestcount": {Amount: 1}, 211 }), 212 perf.BuildBasicCheck( 213 attr3, 214 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 215 "requestcount": {Amount: 1}, 216 }), 217 perf.BuildBasicCheck( 218 attr4, 219 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 220 "requestcount": {Amount: 1}, 221 }), 222 perf.BuildBasicCheck( 223 attr5, 224 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 225 "requestcount": {Amount: 1}, 226 }), 227 }, 228 }, 229 { 230 Multiplier: 1, 231 Requests: []perf.Request{ 232 perf.BuildBasicCheck( 233 attr1, 234 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 235 "requestcount": {Amount: 1}, 236 }), 237 perf.BuildBasicCheck( 238 attr2, 239 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 240 "requestcount": {Amount: 1}, 241 }), 242 perf.BuildBasicCheck( 243 attr3, 244 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 245 "requestcount": {Amount: 1}, 246 }), 247 perf.BuildBasicCheck( 248 attr4, 249 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 250 "requestcount": {Amount: 1}, 251 }), 252 perf.BuildBasicCheck( 253 attr5, 254 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 255 "requestcount": {Amount: 1}, 256 }), 257 }, 258 }, 259 { 260 Multiplier: 1, 261 Requests: []perf.Request{ 262 perf.BuildBasicCheck( 263 attr1, 264 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 265 "requestcount": {Amount: 1}, 266 }), 267 perf.BuildBasicCheck( 268 attr2, 269 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 270 "requestcount": {Amount: 1}, 271 }), 272 perf.BuildBasicCheck( 273 attr3, 274 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 275 "requestcount": {Amount: 1}, 276 }), 277 perf.BuildBasicCheck( 278 attr4, 279 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 280 "requestcount": {Amount: 1}, 281 }), 282 perf.BuildBasicCheck( 283 attr5, 284 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 285 "requestcount": {Amount: 1}, 286 }), 287 }, 288 }, 289 { 290 Multiplier: 1, 291 Requests: []perf.Request{ 292 perf.BuildBasicCheck( 293 attr1, 294 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 295 "requestcount": {Amount: 1}, 296 }), 297 perf.BuildBasicCheck( 298 attr2, 299 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 300 "requestcount": {Amount: 1}, 301 }), 302 perf.BuildBasicCheck( 303 attr3, 304 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 305 "requestcount": {Amount: 1}, 306 }), 307 perf.BuildBasicCheck( 308 attr4, 309 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 310 "requestcount": {Amount: 1}, 311 }), 312 perf.BuildBasicCheck( 313 attr5, 314 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 315 "requestcount": {Amount: 1}, 316 }), 317 }, 318 }, 319 }, 320 } 321 322 perf.Run(b, &setup, settings) 323 validateQuotaBehavior(spyAdapter, b) 324} 325 326// Tests 4 async client, each sending 5 identical quota call into Mixer that dispatches instances to 327// multiple noop inproc adapters. The APA in this case is a slow by 1ms. 328func Benchmark_Quota_4Clients_5SameCallsEach_1MilliSecSlowApa(b *testing.B) { 329 settings, spyAdapter := settingsWith1milliSecApaAdapterAndTmpls() 330 settings.RunMode = perf.InProcess 331 setup := perf.Setup{ 332 Config: perf.Config{ 333 Global: mixerGlobalCfg, 334 Service: quotaInstToSpyAdapter + attrGenToSpyAdapter, 335 }, 336 337 Loads: []perf.Load{ 338 { 339 Multiplier: 5, 340 Requests: []perf.Request{ 341 perf.BuildBasicCheck( 342 baseAttr, 343 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 344 "requestcount": {Amount: 1}, 345 }), 346 }, 347 }, 348 { 349 Multiplier: 5, 350 Requests: []perf.Request{ 351 perf.BuildBasicCheck( 352 baseAttr, 353 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 354 "requestcount": {Amount: 1}, 355 }), 356 }, 357 }, 358 { 359 Multiplier: 5, 360 Requests: []perf.Request{ 361 perf.BuildBasicCheck( 362 baseAttr, 363 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 364 "requestcount": {Amount: 1}, 365 }), 366 }, 367 }, 368 { 369 Multiplier: 5, 370 Requests: []perf.Request{ 371 perf.BuildBasicCheck( 372 baseAttr, 373 map[string]istio_mixer_v1.CheckRequest_QuotaParams{ 374 "requestcount": {Amount: 1}, 375 }), 376 }, 377 }, 378 }, 379 } 380 381 perf.Run(b, &setup, settings) 382 validateQuotaBehavior(spyAdapter, b) 383} 384 385func validateQuotaBehavior(spyAdapter *spyadapter.Adapter, b *testing.B) { 386 // validate all went as expected. 387 // 388 // based on the config, there must be, for each quota check call from client, 389 // * single attribute generation call 390 // * single quota check call 391 foundAttrGenCall := false 392 foundQuotaCall := false 393 for _, cc := range spyAdapter.HandlerData.CapturedCalls { 394 if cc.Name == "HandleSampleApaAttributes" && len(cc.Instances) == 1 { 395 foundAttrGenCall = true 396 } 397 if cc.Name == "HandleSampleQuota" && len(cc.Instances) == 1 { 398 foundQuotaCall = true 399 } 400 } 401 402 if !foundAttrGenCall || !foundQuotaCall { 403 b.Errorf("got spy adapter calls %v; want calls with HandleSampleApaAttributes:1 & HandleSampleQuota:1", 404 spyAdapter.HandlerData.CapturedCalls) 405 } 406} 407 408const ( 409 // contains 1 rules that pass 1 instance to a quota adapter 410 quotaInstToSpyAdapter = ` 411apiVersion: "config.istio.io/v1alpha2" 412kind: spyadapter 413metadata: 414 name: spyadapterHandler 415 namespace: istio-system 416spec: 417--- 418apiVersion: "config.istio.io/v1alpha2" 419kind: samplequota 420metadata: 421 name: requestcount 422 namespace: istio-system 423spec: 424 dimensions: 425 source: source.labels["app"] | source.service | "unknown" 426 sourceVersion: source.labels["version"] | "unknown" 427 destination: destination.labels["app"] | destination.service | "unknown" 428 destinationVersion: destination.labels["version"] | "unknown" 429--- 430apiVersion: "config.istio.io/v1alpha2" 431kind: rule 432metadata: 433 name: quota 434 namespace: istio-system 435spec: 436 actions: 437 - handler: spyadapterHandler.spyadapter 438 instances: 439 - requestcount.samplequota 440--- 441` 442) 443