service-capacity-modeling 0.3.52__py3-none-any.whl → 0.3.54__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of service-capacity-modeling might be problematic. Click here for more details.

@@ -511,6 +511,7 @@ class CapacityPlanner:
511
511
  num_results: Optional[int] = None,
512
512
  num_regions: int = 3,
513
513
  extra_model_arguments: Optional[Dict[str, Any]] = None,
514
+ max_results_per_family: int = 1,
514
515
  ) -> Sequence[CapacityPlan]:
515
516
  if model_name not in self._models:
516
517
  raise ValueError(
@@ -538,6 +539,7 @@ class CapacityPlanner:
538
539
  lifecycles=lifecycles,
539
540
  instance_families=instance_families,
540
541
  drives=drives,
542
+ max_results_per_family=max_results_per_family,
541
543
  )
542
544
  if sub_plan:
543
545
  results.append(sub_plan)
@@ -555,6 +557,7 @@ class CapacityPlanner:
555
557
  instance_families: Optional[Sequence[str]] = None,
556
558
  drives: Optional[Sequence[str]] = None,
557
559
  extra_model_arguments: Optional[Dict[str, Any]] = None,
560
+ max_results_per_family: int = 1,
558
561
  ) -> Sequence[CapacityPlan]:
559
562
  extra_model_arguments = extra_model_arguments or {}
560
563
  model = self._models[model_name]
@@ -577,7 +580,9 @@ class CapacityPlanner:
577
580
  plans.sort(key=lambda p: (p.rank, p.candidate_clusters.total_annual_cost))
578
581
 
579
582
  num_results = num_results or self._default_num_results
580
- return reduce_by_family(plans)[:num_results]
583
+ return reduce_by_family(plans, max_results_per_family=max_results_per_family)[
584
+ :num_results
585
+ ]
581
586
 
582
587
  # Calculates the minimum cpu, memory, and network requirements based on desires.
583
588
  def _per_instance_requirements(self, desires) -> Tuple[int, float]:
@@ -696,6 +701,7 @@ class CapacityPlanner:
696
701
  regret_params: Optional[CapacityRegretParameters] = None,
697
702
  extra_model_arguments: Optional[Dict[str, Any]] = None,
698
703
  explain: bool = False,
704
+ max_results_per_family: int = 1,
699
705
  ) -> UncertainCapacityPlan:
700
706
  extra_model_arguments = extra_model_arguments or {}
701
707
 
@@ -741,6 +747,7 @@ class CapacityPlanner:
741
747
  lifecycles=lifecycles,
742
748
  instance_families=instance_families,
743
749
  drives=drives,
750
+ max_results_per_family=max_results_per_family,
744
751
  ),
745
752
  )
746
753
  )
@@ -763,7 +770,8 @@ class CapacityPlanner:
763
770
  ],
764
771
  zonal_requirements,
765
772
  regional_requirements,
766
- )
773
+ ),
774
+ max_results_per_family=max_results_per_family,
767
775
  )[:num_results]
768
776
 
769
777
  low_p, high_p = sorted(percentiles)[0], sorted(percentiles)[-1]
@@ -164,7 +164,11 @@ def _estimate_cassandra_requirement( # pylint: disable=too-many-positional-argu
164
164
  disk_scale, _ = derived_buffer_for_component(
165
165
  desires.buffers.derived, ["storage", "disk"]
166
166
  )
167
- disk_used_gib = current_capacity.disk_utilization_gib.mid * (disk_scale or 1)
167
+ disk_used_gib = (
168
+ current_capacity.disk_utilization_gib.mid
169
+ * current_capacity.cluster_instance_count.mid
170
+ * (disk_scale or 1)
171
+ )
168
172
  else:
169
173
  # If the cluster is not yet provisioned
170
174
  capacity_requirement = _zonal_requirement_for_new_cluster(
@@ -1,19 +1,26 @@
1
1
  import math
2
+ from typing import Dict
2
3
  from typing import Iterable
3
4
  from typing import List
4
- from typing import Set
5
5
  from typing import Tuple
6
6
 
7
7
  from service_capacity_modeling.models import CapacityPlan
8
8
 
9
9
 
10
- def reduce_by_family(plans: Iterable[CapacityPlan]) -> List[CapacityPlan]:
10
+ def reduce_by_family(
11
+ plans: Iterable[CapacityPlan], max_results_per_family: int = 1
12
+ ) -> List[CapacityPlan]:
11
13
  """Groups a potential set of clusters by hardware family sorted by cost.
12
14
 
13
15
  Useful for showing different family options.
16
+
17
+ Args:
18
+ plans: Iterable of CapacityPlan objects to filter
19
+ max_results_per_family: Maximum number of results to return per
20
+ family combination
14
21
  """
15
- zonal_families: Set[Tuple[Tuple[str, str], ...]] = set()
16
- regional_families: Set[Tuple[Tuple[str, str], ...]] = set()
22
+ zonal_families: Dict[Tuple[Tuple[str, str], ...], int] = {}
23
+ regional_families: Dict[Tuple[Tuple[str, str], ...], int] = {}
17
24
 
18
25
  result: List[CapacityPlan] = []
19
26
  for plan in plans:
@@ -31,11 +38,20 @@ def reduce_by_family(plans: Iterable[CapacityPlan]) -> List[CapacityPlan]:
31
38
  sorted({(c.cluster_type, c.instance.family) for c in topo.zonal})
32
39
  )
33
40
 
34
- if not (zonal_type in zonal_families and regional_type in regional_families):
41
+ # Count how many of each family combination we've seen
42
+ zonal_count = zonal_families.get(zonal_type, 0)
43
+ regional_count = regional_families.get(regional_type, 0)
44
+
45
+ # Add the plan if we haven't reached the maximum for either family type
46
+ if (
47
+ zonal_count < max_results_per_family
48
+ or regional_count < max_results_per_family
49
+ ):
35
50
  result.append(plan)
36
51
 
37
- regional_families.add(regional_type)
38
- zonal_families.add(zonal_type)
52
+ # Update counters
53
+ zonal_families[zonal_type] = zonal_count + 1
54
+ regional_families[regional_type] = regional_count + 1
39
55
 
40
56
  return result
41
57
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: service-capacity-modeling
3
- Version: 0.3.52
3
+ Version: 0.3.54
4
4
  Summary: Contains utilities for modeling capacity for pluggable workloads
5
5
  Author: Joseph Lynch
6
6
  Author-email: josephl@netflix.com
@@ -1,5 +1,5 @@
1
1
  service_capacity_modeling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- service_capacity_modeling/capacity_planner.py,sha256=0lQCQRlnEF2frwuK0cOy5wAkOcr1-6qunBjZPukTcdg,31525
2
+ service_capacity_modeling/capacity_planner.py,sha256=B-C6EgZEWLKS6HEL74WxGeoLHrzNN6Cmyfee2jKsdcU,31915
3
3
  service_capacity_modeling/interface.py,sha256=145YV4Lm2YZhBAKjsdUIjeIOxJ7NxqUPwz9oxekgsPo,36995
4
4
  service_capacity_modeling/stats.py,sha256=8HIPwVnmvbauBwXhn6vbNYO7-CzWPuymnq0eX7ZA1_w,5849
5
5
  service_capacity_modeling/hardware/__init__.py,sha256=Lc-DdX2ZJ_sFT3KlImPUUcKmcjVnavH_mMXlyCwpNiw,9001
@@ -42,11 +42,11 @@ service_capacity_modeling/hardware/profiles/shapes/aws/manual_services.json,sha2
42
42
  service_capacity_modeling/models/__init__.py,sha256=XK7rTBW8ZXQY5L9Uy2FwjuFN_KBW3hKw7IrhG1piajs,13567
43
43
  service_capacity_modeling/models/common.py,sha256=ixmNkohvw30R2JBvdpM6xKb19na_g3GNGvQQYLlkV_A,33577
44
44
  service_capacity_modeling/models/headroom_strategy.py,sha256=QIkP_K_tK2EGAjloaGfXeAPH5M0UDCN8FlAtwV9xxTA,651
45
- service_capacity_modeling/models/utils.py,sha256=Y9xwSzLuGQ7Tn4BCkbdMtR7_fjEQ9PKQ52JlHVtdEtY,1567
45
+ service_capacity_modeling/models/utils.py,sha256=0F__wz9KAGhPIQfvNp-FTtTANW6-sO4FsyddnuXqSJc,2161
46
46
  service_capacity_modeling/models/org/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  service_capacity_modeling/models/org/netflix/__init__.py,sha256=m7IaQbo85NEbDvfoPJREIznpzg0YHTCrKP5C1GvnOYM,2378
48
48
  service_capacity_modeling/models/org/netflix/aurora.py,sha256=Mi9zd48k64GkKIjAs3J1S2qThguNvyWIy2dUmhwrVhc,12883
49
- service_capacity_modeling/models/org/netflix/cassandra.py,sha256=g4APPpii5Pq9WbO2yYORL0tdmLhNujAR_m-qh-D2HZY,32415
49
+ service_capacity_modeling/models/org/netflix/cassandra.py,sha256=kJ68ufYTo849Zsh6_BXn-mSLse0ZHsMEP0yuzeFrTzE,32509
50
50
  service_capacity_modeling/models/org/netflix/counter.py,sha256=hOVRRCgCPU-A5TdLKQXc_mWTQpkKOWRNjOeECdDP7kA,9205
51
51
  service_capacity_modeling/models/org/netflix/crdb.py,sha256=2rD4Io0yT7o0NR4lNferXXOSTDe0SkT1LbSChvNgRrQ,19698
52
52
  service_capacity_modeling/models/org/netflix/ddb.py,sha256=2jxMFz31xckJvymvVlu1yWm0X4dGYlqxDo0bftU1B9M,26307
@@ -69,9 +69,9 @@ service_capacity_modeling/tools/auto_shape.py,sha256=Rk5Fjrw2susVL8It_J2KUADoMGB
69
69
  service_capacity_modeling/tools/fetch_pricing.py,sha256=SHOtFaPr61op2bnY9i_g_1-d-Nz2rV8c7Jwsye2R49s,3763
70
70
  service_capacity_modeling/tools/generate_missing.py,sha256=WN7Y0iPjelJu9d2Yq5dcu_EBIQPX2VxKgOou4NMNOM4,2860
71
71
  service_capacity_modeling/tools/instance_families.py,sha256=e9JWSIdljSmHI8Nb2MI5Ld9JqQ7WdOtPtV7g3oR7ZiU,7764
72
- service_capacity_modeling-0.3.52.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
73
- service_capacity_modeling-0.3.52.dist-info/METADATA,sha256=eEwFJewSmbZuxbw3EbFMzicgLyxAVmnBsUI5OBtX8Sc,9590
74
- service_capacity_modeling-0.3.52.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
75
- service_capacity_modeling-0.3.52.dist-info/entry_points.txt,sha256=ZsjzpG5SomWpT1zCE19n1uSXKH2gTI_yc33sdl0vmJg,146
76
- service_capacity_modeling-0.3.52.dist-info/top_level.txt,sha256=H8XjTCLgR3enHq5t3bIbxt9SeUkUT8HT_SDv2dgIT_A,26
77
- service_capacity_modeling-0.3.52.dist-info/RECORD,,
72
+ service_capacity_modeling-0.3.54.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
73
+ service_capacity_modeling-0.3.54.dist-info/METADATA,sha256=MnEqceUIId8ws3qU2vAxDhVF6MCKBCDc74tq_c4WE54,9590
74
+ service_capacity_modeling-0.3.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
75
+ service_capacity_modeling-0.3.54.dist-info/entry_points.txt,sha256=ZsjzpG5SomWpT1zCE19n1uSXKH2gTI_yc33sdl0vmJg,146
76
+ service_capacity_modeling-0.3.54.dist-info/top_level.txt,sha256=H8XjTCLgR3enHq5t3bIbxt9SeUkUT8HT_SDv2dgIT_A,26
77
+ service_capacity_modeling-0.3.54.dist-info/RECORD,,