1717]
1818
1919ProfileGenerationMode = Literal [
20- "sweep" , "synchronous" , "throughput" , "constant" , "poisson"
20+ "sweep" , "synchronous" , "throughput" , "constant" , "poisson" , "concurrent"
2121]
2222
2323
@@ -34,7 +34,7 @@ class Profile(Serializable):
3434 """
3535
3636 load_gen_mode : LoadGenerationMode
37- load_gen_rate : Optional [float ] = None
37+ load_gen_rate : Optional [Union [ float , int ] ] = None
3838 args : Dict [str , Any ] = Field (default_factory = dict )
3939
4040
@@ -45,6 +45,7 @@ class ProfileGenerator:
4545 :param mode: The mode for profile generation (e.g., sweep, synchronous).
4646 :type mode: ProfileGenerationMode
4747 :param rate: The rate(s) for load generation; could be a float or list of floats.
48+ In case ``mode`` is concurrent - integer which is the number of streams.
4849 :type rate: Optional[Union[float, Sequence[float]]]
4950 """
5051
@@ -61,7 +62,7 @@ def __init__(
6162 logger .error (err )
6263 raise err
6364
64- self ._mode = mode
65+ self ._mode : ProfileGenerationMode = mode
6566
6667 if self ._mode in ("sweep" , "throughput" , "synchronous" ):
6768 if rate is not None :
@@ -74,6 +75,7 @@ def __init__(
7475 err = ValueError (f"Rates are required for { self ._mode } mode" )
7576 logger .error (err )
7677 raise err
78+
7779 self ._rates = rate if isinstance (rate , Sequence ) else [rate ]
7880
7981 for rt in self ._rates :
@@ -96,13 +98,13 @@ def __len__(self) -> int:
9698 if self ._mode == "sweep" :
9799 return settings .num_sweep_profiles + 2
98100
99- if self ._mode in ("throughput" , "synchronous" ):
101+ if self ._mode in ("throughput" , "synchronous" , "concurrent" ):
100102 return 1
101103
102- if not self ._rates :
104+ if not self .rates :
103105 raise ValueError (f"Rates are required for { self ._mode } mode" )
104106
105- return len (self ._rates )
107+ return len (self .rates )
106108
107109 @property
108110 def mode (self ) -> ProfileGenerationMode :
@@ -147,7 +149,7 @@ def profile_generation_modes(self) -> Sequence[ProfileGenerationMode]:
147149 settings .num_sweep_profiles
148150 )
149151
150- if self ._mode in ["throughput" , "synchronous" ]:
152+ if self ._mode in ["throughput" , "synchronous" , "concurrent" ]:
151153 return [self ._mode ]
152154
153155 if self ._rates is None :
@@ -188,6 +190,19 @@ def next(self, current_report: TextGenerationBenchmarkReport) -> Optional[Profil
188190 profile = self .create_synchronous_profile (self .generated_count )
189191 elif self .mode == "throughput" :
190192 profile = self .create_throughput_profile (self .generated_count )
193+ elif self .mode == "concurrent" :
194+ err = ValueError (
195+ f"Can not create concurrent profile with rate { self .rates } "
196+ )
197+ try :
198+ if not self .rates :
199+ raise err
200+
201+ _rate : int = int (self .rates [0 ])
202+ except IndexError as error :
203+ logger .error (err )
204+ raise err from error
205+ profile = self .create_concurrent_profile (self .generated_count , _rate )
191206 elif self .mode == "sweep" :
192207 profile = self .create_sweep_profile (
193208 self .generated_count ,
@@ -211,6 +226,7 @@ def next(self, current_report: TextGenerationBenchmarkReport) -> Optional[Profil
211226 profile ,
212227 self ._generated_count ,
213228 )
229+
214230 return profile
215231
216232 @staticmethod
@@ -229,9 +245,11 @@ def create_fixed_rate_profile(
229245 :return: The generated profile or None if index is out of range.
230246 :rtype: Optional[Profile]
231247 """
248+
232249 modes_map : Dict [str , LoadGenerationMode ] = {
233250 "constant" : "constant" ,
234251 "poisson" : "poisson" ,
252+ "concurrent" : "concurrent" ,
235253 }
236254
237255 if mode not in modes_map :
@@ -348,3 +366,26 @@ def create_sweep_profile(
348366 else 1.0 # the fallback value
349367 ),
350368 )
369+
370+ @staticmethod
371+ def create_concurrent_profile (index : int , rate : int ) -> Optional [Profile ]:
372+ """
373+ Creates a profile with concurrent constant mode.
374+
375+ :param index: The index of the profile to create.
376+ :type index: int
377+ :return: The generated profile or None if index is out of range.
378+ :rtype: Optional[Profile]
379+ """
380+
381+ profile = (
382+ Profile (
383+ load_gen_mode = "concurrent" ,
384+ load_gen_rate = rate ,
385+ )
386+ if index < 1
387+ else None
388+ )
389+ logger .debug ("Created concurrent profile: {}" , profile )
390+
391+ return profile
0 commit comments