service-capacity-modeling 0.3.51__py3-none-any.whl → 0.3.53__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.
- service_capacity_modeling/models/org/netflix/cassandra.py +5 -1
- service_capacity_modeling/models/org/netflix/kafka.py +120 -76
- {service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/METADATA +1 -1
- {service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/RECORD +8 -8
- {service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/WHEEL +0 -0
- {service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/entry_points.txt +0 -0
- {service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/licenses/LICENSE +0 -0
- {service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/top_level.txt +0 -0
|
@@ -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 =
|
|
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(
|
|
@@ -11,6 +11,9 @@ from pydantic import Field
|
|
|
11
11
|
|
|
12
12
|
from service_capacity_modeling.interface import AccessConsistency
|
|
13
13
|
from service_capacity_modeling.interface import AccessPattern
|
|
14
|
+
from service_capacity_modeling.interface import Buffer
|
|
15
|
+
from service_capacity_modeling.interface import BufferComponent
|
|
16
|
+
from service_capacity_modeling.interface import Buffers
|
|
14
17
|
from service_capacity_modeling.interface import CapacityDesires
|
|
15
18
|
from service_capacity_modeling.interface import CapacityPlan
|
|
16
19
|
from service_capacity_modeling.interface import CapacityRequirement
|
|
@@ -31,9 +34,11 @@ from service_capacity_modeling.interface import QueryPattern
|
|
|
31
34
|
from service_capacity_modeling.interface import RegionContext
|
|
32
35
|
from service_capacity_modeling.interface import Requirements
|
|
33
36
|
from service_capacity_modeling.models import CapacityModel
|
|
37
|
+
from service_capacity_modeling.models import utils
|
|
34
38
|
from service_capacity_modeling.models.common import compute_stateful_zone
|
|
35
39
|
from service_capacity_modeling.models.common import normalize_cores
|
|
36
40
|
from service_capacity_modeling.models.common import sqrt_staffed_cores
|
|
41
|
+
from service_capacity_modeling.models.common import zonal_requirements_from_current
|
|
37
42
|
from service_capacity_modeling.models.org.netflix.iso_date_math import iso_to_seconds
|
|
38
43
|
|
|
39
44
|
logger = logging.getLogger(__name__)
|
|
@@ -44,15 +49,6 @@ class ClusterType(str, Enum):
|
|
|
44
49
|
ha = "high-availability"
|
|
45
50
|
|
|
46
51
|
|
|
47
|
-
def target_cpu_utilization(tier: int) -> float:
|
|
48
|
-
"""
|
|
49
|
-
Returns the target average cluster CPU utilization for a given tier
|
|
50
|
-
"""
|
|
51
|
-
if tier in (0, 1):
|
|
52
|
-
return 0.40
|
|
53
|
-
return 0.50
|
|
54
|
-
|
|
55
|
-
|
|
56
52
|
def _get_current_zonal_cluster(
|
|
57
53
|
desires: CapacityDesires,
|
|
58
54
|
) -> Optional[CurrentZoneClusterCapacity]:
|
|
@@ -108,54 +104,8 @@ def _estimate_kafka_requirement( # pylint: disable=too-many-positional-argument
|
|
|
108
104
|
write_mib_per_second
|
|
109
105
|
)
|
|
110
106
|
# use the current cluster capacity if available
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
current_zonal_cluster
|
|
115
|
-
and current_zonal_cluster.cluster_instance
|
|
116
|
-
and required_zone_size is not None
|
|
117
|
-
):
|
|
118
|
-
# For now, use the highest average CPU utilization seen on the cluster
|
|
119
|
-
cpu_utilization = current_zonal_cluster.cpu_utilization.high
|
|
120
|
-
# Validate with data if we should instead estimate 99th percentile here to get
|
|
121
|
-
# rid of spikes in collected cpu usage data ?
|
|
122
|
-
# Use the formula: 99th Percentile ≈ Average + (Z-score * SD).
|
|
123
|
-
# https://en.wikipedia.org/wiki/Normal_curve_equivalent#:~:text=The%2099th%20percentile%20in%20a,49/2.3263%20=%2021.06.
|
|
124
|
-
# curr_cpu_util = cpu_util.mid + (2.33 * (cpu_util.high - cpu_util.low) / 6)
|
|
125
|
-
current_utilized_cores = (
|
|
126
|
-
current_zonal_cluster.cluster_instance.cpu
|
|
127
|
-
* required_zone_size
|
|
128
|
-
* zones_per_region
|
|
129
|
-
* cpu_utilization
|
|
130
|
-
) / 100
|
|
131
|
-
|
|
132
|
-
# compute needed core capacity for cluster so avg cpu utilization for the
|
|
133
|
-
# cluster stays under threshold for that tier
|
|
134
|
-
needed_cores = int(
|
|
135
|
-
current_utilized_cores / target_cpu_utilization(desires.service_tier)
|
|
136
|
-
)
|
|
137
|
-
logger.debug("kafka needed cores: %s", needed_cores)
|
|
138
|
-
# Normalize those cores to the target shape
|
|
139
|
-
reference_shape = current_zonal_cluster.cluster_instance
|
|
140
|
-
needed_cores = normalize_cores(
|
|
141
|
-
core_count=needed_cores,
|
|
142
|
-
target_shape=instance,
|
|
143
|
-
reference_shape=reference_shape,
|
|
144
|
-
)
|
|
145
|
-
logger.debug("kafka normalized needed cores: %s", needed_cores)
|
|
146
|
-
else:
|
|
147
|
-
# We have no existing utilization to go from
|
|
148
|
-
needed_cores = normalize_cores(
|
|
149
|
-
core_count=sqrt_staffed_cores(normalized_to_mib),
|
|
150
|
-
target_shape=instance,
|
|
151
|
-
reference_shape=desires.reference_shape,
|
|
152
|
-
)
|
|
107
|
+
current_zonal_capacity = _get_current_zonal_cluster(desires)
|
|
153
108
|
|
|
154
|
-
# (Nick): Keep 40% of available bandwidth for node recovery
|
|
155
|
-
# (Joey): For kafka BW = BW_write + BW_reads
|
|
156
|
-
# let X = input write BW
|
|
157
|
-
# BW_in = X * RF
|
|
158
|
-
# BW_out = X * (consumers) + X * (RF - 1)
|
|
159
109
|
bw_in = (
|
|
160
110
|
(write_mib_per_second * MIB_IN_BYTES) * copies_per_region
|
|
161
111
|
) / MEGABIT_IN_BYTES
|
|
@@ -165,21 +115,78 @@ def _estimate_kafka_requirement( # pylint: disable=too-many-positional-argument
|
|
|
165
115
|
+ ((write_mib_per_second * MIB_IN_BYTES) * (copies_per_region - 1))
|
|
166
116
|
)
|
|
167
117
|
) / MEGABIT_IN_BYTES
|
|
168
|
-
|
|
169
|
-
|
|
118
|
+
if (
|
|
119
|
+
current_zonal_capacity
|
|
120
|
+
and current_zonal_capacity.cluster_instance
|
|
121
|
+
and required_zone_size is not None
|
|
122
|
+
and desires.current_clusters is not None
|
|
123
|
+
):
|
|
124
|
+
# zonal_requirements_from_current uses the midpoint utilization of the
|
|
125
|
+
# current cluster. For Kafka, we want to use the high value instead
|
|
126
|
+
# for cpu, disk, network, etc.
|
|
127
|
+
normalize_midpoint_desires = desires.model_copy(deep=True)
|
|
128
|
+
# This is checked in the if statement above. Assert here for mypy linter purpose
|
|
129
|
+
assert normalize_midpoint_desires.current_clusters is not None
|
|
130
|
+
curr_disk = desires.current_clusters.zonal[0].disk_utilization_gib
|
|
131
|
+
curr_cpu = desires.current_clusters.zonal[0].cpu_utilization
|
|
132
|
+
curr_network = desires.current_clusters.zonal[0].network_utilization_mbps
|
|
133
|
+
normalize_midpoint_desires.current_clusters.zonal[
|
|
134
|
+
0
|
|
135
|
+
].disk_utilization_gib = Interval(
|
|
136
|
+
low=curr_disk.high, mid=curr_disk.high, high=curr_disk.high
|
|
137
|
+
)
|
|
138
|
+
normalize_midpoint_desires.current_clusters.zonal[0].cpu_utilization = Interval(
|
|
139
|
+
low=curr_cpu.high, mid=curr_cpu.high, high=curr_cpu.high
|
|
140
|
+
)
|
|
141
|
+
normalize_midpoint_desires.current_clusters.zonal[
|
|
142
|
+
0
|
|
143
|
+
].network_utilization_mbps = Interval(
|
|
144
|
+
low=curr_network.high, mid=curr_network.high, high=curr_network.high
|
|
145
|
+
)
|
|
146
|
+
capacity_requirement = zonal_requirements_from_current(
|
|
147
|
+
current_cluster=normalize_midpoint_desires.current_clusters,
|
|
148
|
+
buffers=desires.buffers,
|
|
149
|
+
instance=instance,
|
|
150
|
+
reference_shape=current_zonal_capacity.cluster_instance,
|
|
151
|
+
)
|
|
152
|
+
needed_cores = int(capacity_requirement.cpu_cores.mid)
|
|
153
|
+
needed_disk = int(capacity_requirement.disk_gib.mid)
|
|
154
|
+
needed_network_mbps = int(capacity_requirement.network_mbps.mid)
|
|
155
|
+
logger.debug(
|
|
156
|
+
"kafka normalized needed cores: %s", capacity_requirement.cpu_cores
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
# We have no existing utilization to go from
|
|
160
|
+
needed_cores = (
|
|
161
|
+
normalize_cores(
|
|
162
|
+
core_count=sqrt_staffed_cores(normalized_to_mib),
|
|
163
|
+
target_shape=instance,
|
|
164
|
+
reference_shape=desires.reference_shape,
|
|
165
|
+
)
|
|
166
|
+
// zones_per_region
|
|
167
|
+
)
|
|
170
168
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
169
|
+
# (Nick): Keep 40% of available bandwidth for node recovery
|
|
170
|
+
# (Joey): For kafka BW = BW_write + BW_reads
|
|
171
|
+
# let X = input write BW
|
|
172
|
+
# BW_in = X * RF
|
|
173
|
+
# BW_out = X * (consumers) + X * (RF - 1)
|
|
174
|
+
# BW = (in + out) because duplex then 40% headroom.
|
|
175
|
+
needed_network_mbps = int((max(bw_in, bw_out) * 1.40) // zones_per_region)
|
|
176
|
+
|
|
177
|
+
# NOTE: data_shape is region, we need to convert it to zonal
|
|
178
|
+
# If we don't have an existing cluster, the estimated state size should be
|
|
179
|
+
# at most 40% of the total cluster's available disk.
|
|
180
|
+
# i.e. needed_disk = state_size * 2.5
|
|
181
|
+
needed_disk = math.ceil(
|
|
182
|
+
(desires.data_shape.estimated_state_size_gib.mid // zones_per_region) * 2.5,
|
|
183
|
+
)
|
|
174
184
|
|
|
175
185
|
# Keep the last N seconds hot in cache
|
|
176
|
-
needed_memory = (
|
|
186
|
+
needed_memory = (
|
|
187
|
+
(write_mib_per_second * hot_retention_seconds) // 1024
|
|
188
|
+
) // zones_per_region
|
|
177
189
|
|
|
178
|
-
# Now convert to per zone
|
|
179
|
-
needed_cores = max(1, needed_cores // zones_per_region)
|
|
180
|
-
needed_disk = max(1, needed_disk // zones_per_region)
|
|
181
|
-
needed_memory = max(1, int(needed_memory // zones_per_region))
|
|
182
|
-
needed_network_mbps = max(1, int(needed_network_mbps // zones_per_region))
|
|
183
190
|
logger.debug(
|
|
184
191
|
"Need (cpu, mem, disk) = (%s, %s, %s)",
|
|
185
192
|
needed_cores,
|
|
@@ -218,7 +225,8 @@ def _kafka_read_io(rps, io_size_kib, size_gib, recovery_seconds: int) -> float:
|
|
|
218
225
|
# In practice we have cache reducing this by 99% or more
|
|
219
226
|
read_ios = rps * 0.05
|
|
220
227
|
# Recover the node in 60 minutes, to do that we need
|
|
221
|
-
|
|
228
|
+
# Estimate that we are using ~ 50% of the disk prior to a recovery
|
|
229
|
+
size_kib = size_gib * 0.5 * (1024 * 1024)
|
|
222
230
|
recovery_ios = max(1, size_kib / io_size_kib) / recovery_seconds
|
|
223
231
|
# Leave 50% headroom for read IOs since generally we will hit cache
|
|
224
232
|
return (read_ios + int(round(recovery_ios))) * 1.5
|
|
@@ -226,7 +234,8 @@ def _kafka_read_io(rps, io_size_kib, size_gib, recovery_seconds: int) -> float:
|
|
|
226
234
|
|
|
227
235
|
# pylint: disable=too-many-locals
|
|
228
236
|
# pylint: disable=too-many-return-statements
|
|
229
|
-
|
|
237
|
+
# pylint: disable=too-many-positional-arguments
|
|
238
|
+
def _estimate_kafka_cluster_zonal(
|
|
230
239
|
instance: Instance,
|
|
231
240
|
drive: Drive,
|
|
232
241
|
desires: CapacityDesires,
|
|
@@ -306,6 +315,7 @@ def _estimate_kafka_cluster_zonal( # pylint: disable=too-many-positional-argume
|
|
|
306
315
|
write_ios_per_second = max(
|
|
307
316
|
1, (write_mib_per_second * 1024) // drive.seq_io_size_kib
|
|
308
317
|
)
|
|
318
|
+
max_attached_disk_gib = 8 * 1024
|
|
309
319
|
|
|
310
320
|
cluster = compute_stateful_zone(
|
|
311
321
|
instance=instance,
|
|
@@ -329,8 +339,8 @@ def _estimate_kafka_cluster_zonal( # pylint: disable=too-many-positional-argume
|
|
|
329
339
|
# Leave 100% IO headroom for writes
|
|
330
340
|
copies_per_region * (write_ios_per_second / count) * 2,
|
|
331
341
|
),
|
|
332
|
-
#
|
|
333
|
-
required_disk_space=lambda x: x
|
|
342
|
+
# Disk buffer is already added when computing kafka disk requirements
|
|
343
|
+
required_disk_space=lambda x: x,
|
|
334
344
|
max_local_disk_gib=max_local_disk_gib,
|
|
335
345
|
cluster_size=lambda x: x,
|
|
336
346
|
min_count=max(min_count, required_zone_size or 1),
|
|
@@ -338,17 +348,34 @@ def _estimate_kafka_cluster_zonal( # pylint: disable=too-many-positional-argume
|
|
|
338
348
|
# Kafka currently uses 8GiB fixed, might want to change to min(30, x // 2)
|
|
339
349
|
reserve_memory=lambda instance_mem_gib: base_mem + 8,
|
|
340
350
|
# allow up to 8TiB of attached EBS
|
|
341
|
-
max_attached_disk_gib=
|
|
351
|
+
max_attached_disk_gib=max_attached_disk_gib,
|
|
342
352
|
)
|
|
343
353
|
|
|
344
354
|
# Communicate to the actual provision that if we want reduced RF
|
|
345
355
|
params = {"kafka.copies": copies_per_region}
|
|
346
356
|
_upsert_params(cluster, params)
|
|
347
357
|
|
|
348
|
-
#
|
|
349
|
-
#
|
|
350
|
-
if required_zone_size is not None
|
|
351
|
-
|
|
358
|
+
# This is roughly the disk we would have tried to provision with the current
|
|
359
|
+
# cluster's instance count (or required_zone_size)
|
|
360
|
+
if required_zone_size is not None:
|
|
361
|
+
space_gib = max(1, math.ceil(requirement.disk_gib.mid / required_zone_size))
|
|
362
|
+
ebs_gib = utils.next_n(space_gib, n=100)
|
|
363
|
+
max_size = (
|
|
364
|
+
max_attached_disk_gib
|
|
365
|
+
if max_attached_disk_gib is not None
|
|
366
|
+
else drive.max_size_gib / 3
|
|
367
|
+
) # Max allowed disk in `compute_stateful_zone`
|
|
368
|
+
|
|
369
|
+
# Capacity planner only allows ~ 5TB disk (max_size) for gp3 drives
|
|
370
|
+
# or max_attached_disk_gib if provided.
|
|
371
|
+
# If ebs_gib > max_size, we do not have enough instances within the
|
|
372
|
+
# required_zone_size for the required disk. In these cases, it is
|
|
373
|
+
# not possible for cluster.count == required_zone_size. We should
|
|
374
|
+
# allow higher instance count for these cases so that we return some result
|
|
375
|
+
# If we did not exceed the max disk size with the required_zone_size, then
|
|
376
|
+
# we only allow topologies that match the desired zone size
|
|
377
|
+
if ebs_gib <= max_size and cluster.count != required_zone_size:
|
|
378
|
+
return None
|
|
352
379
|
|
|
353
380
|
# Kafka clusters generally should try to stay under some total number
|
|
354
381
|
# of nodes. Orgs do this for all kinds of reasons such as
|
|
@@ -542,6 +569,22 @@ class NflxKafkaCapacityModel(CapacityModel):
|
|
|
542
569
|
write_bytes.mid * retention_secs * replication_factor
|
|
543
570
|
) / GIB_IN_BYTES
|
|
544
571
|
|
|
572
|
+
# By supplying these buffers we can deconstruct observed utilization into
|
|
573
|
+
# load versus buffer.
|
|
574
|
+
compute_buffer_ratio = 2.5 if user_desires.service_tier in (0, 1) else 2.0
|
|
575
|
+
buffers = Buffers(
|
|
576
|
+
default=Buffer(ratio=1.5),
|
|
577
|
+
desired={
|
|
578
|
+
# Amount of compute buffer that we need to reserve in addition to
|
|
579
|
+
# cpu_headroom_target that is reserved on a per instance basis
|
|
580
|
+
"compute": Buffer(
|
|
581
|
+
ratio=compute_buffer_ratio, components=[BufferComponent.compute]
|
|
582
|
+
),
|
|
583
|
+
# This makes sure we use only 40% of the available storage
|
|
584
|
+
"storage": Buffer(ratio=2.5, components=[BufferComponent.storage]),
|
|
585
|
+
},
|
|
586
|
+
)
|
|
587
|
+
|
|
545
588
|
return CapacityDesires(
|
|
546
589
|
query_pattern=QueryPattern(
|
|
547
590
|
access_pattern=AccessPattern.throughput,
|
|
@@ -581,6 +624,7 @@ class NflxKafkaCapacityModel(CapacityModel):
|
|
|
581
624
|
# Connection overhead, kernel, etc ...
|
|
582
625
|
reserved_instance_system_mem_gib=3,
|
|
583
626
|
),
|
|
627
|
+
buffers=buffers,
|
|
584
628
|
)
|
|
585
629
|
|
|
586
630
|
|
{service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/RECORD
RENAMED
|
@@ -46,7 +46,7 @@ service_capacity_modeling/models/utils.py,sha256=Y9xwSzLuGQ7Tn4BCkbdMtR7_fjEQ9PK
|
|
|
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=
|
|
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
|
|
@@ -55,7 +55,7 @@ service_capacity_modeling/models/org/netflix/entity.py,sha256=M0vzwhf8UAbVxnXspA
|
|
|
55
55
|
service_capacity_modeling/models/org/netflix/evcache.py,sha256=l3fzIVQ1PznD2tG00Fmwl728437MZrtHOS4WjXVa3fs,25229
|
|
56
56
|
service_capacity_modeling/models/org/netflix/graphkv.py,sha256=EVRo-1OCDvvotqPgIdP2_JXMfZUsG7KZxRMmlgYc3CI,8558
|
|
57
57
|
service_capacity_modeling/models/org/netflix/iso_date_math.py,sha256=CPGHLmbGeNqkcYcmCkLKhPZcAU-yTJ2HjvuXdnNyCYc,996
|
|
58
|
-
service_capacity_modeling/models/org/netflix/kafka.py,sha256=
|
|
58
|
+
service_capacity_modeling/models/org/netflix/kafka.py,sha256=bxmrvP39ILPKFpBtanOyjVUEtSXUJGKpiSEHdKLUgcM,25339
|
|
59
59
|
service_capacity_modeling/models/org/netflix/key_value.py,sha256=yL5moU0SJD4ocBU9zeGhPYE4KY7oSSq5yqfVWd_Ot2g,9336
|
|
60
60
|
service_capacity_modeling/models/org/netflix/postgres.py,sha256=R3Tog-ZW1Yx6gO3AKqI_wquSm30s01QX9yWR7Jvgk9A,4055
|
|
61
61
|
service_capacity_modeling/models/org/netflix/rds.py,sha256=z9egFBg4Ltqyuz_WHk-_hw-xL-EQNzl1JopJoWdNli8,10768
|
|
@@ -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.
|
|
73
|
-
service_capacity_modeling-0.3.
|
|
74
|
-
service_capacity_modeling-0.3.
|
|
75
|
-
service_capacity_modeling-0.3.
|
|
76
|
-
service_capacity_modeling-0.3.
|
|
77
|
-
service_capacity_modeling-0.3.
|
|
72
|
+
service_capacity_modeling-0.3.53.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
|
|
73
|
+
service_capacity_modeling-0.3.53.dist-info/METADATA,sha256=Bip_YLLrgI7oTgIctl9rxmgxdqVr0DuQycV8lzOsDWU,9590
|
|
74
|
+
service_capacity_modeling-0.3.53.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
75
|
+
service_capacity_modeling-0.3.53.dist-info/entry_points.txt,sha256=ZsjzpG5SomWpT1zCE19n1uSXKH2gTI_yc33sdl0vmJg,146
|
|
76
|
+
service_capacity_modeling-0.3.53.dist-info/top_level.txt,sha256=H8XjTCLgR3enHq5t3bIbxt9SeUkUT8HT_SDv2dgIT_A,26
|
|
77
|
+
service_capacity_modeling-0.3.53.dist-info/RECORD,,
|
{service_capacity_modeling-0.3.51.dist-info → service_capacity_modeling-0.3.53.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|