Skip to content

Commit 4c6cc14

Browse files
author
Krish
committed
no need of dynamic nature
1 parent 5fef5c1 commit 4c6cc14

File tree

5 files changed

+28
-85
lines changed

5 files changed

+28
-85
lines changed

include/aws/s3/private/s3_meta_request_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ struct aws_s3_meta_request {
155155
struct aws_parallel_input_stream *request_body_parallel_stream;
156156
bool request_body_using_async_writes;
157157

158+
/* object_size based on the earliest estimate */
159+
size_t object_size;
158160
/* Part size to use for uploads and downloads. Passed down by the creating client. */
159161
const size_t part_size;
160162
/* Hard limit on max connections set through the meta request option. */

source/s3_auto_ranged_get.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,8 @@ static int s_discover_object_range_and_size(
619619
* total_content_length. */
620620
if (!auto_ranged_get->initial_message_has_range_header) {
621621
object_size = content_length;
622+
/* copy it to meta request */
623+
meta_request->object_size = object_size;
622624
if (content_length > 0) {
623625
object_range_end = content_length - 1; /* range-end is inclusive */
624626
}

source/s3_client.c

Lines changed: 17 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -191,82 +191,6 @@ static uint32_t s_get_system_fd_limit(void) {
191191
#endif
192192
}
193193

194-
/**
195-
* Calculate dynamic connection limit based on sum of active meta request requirements.
196-
* Returns the minimum of: total required connections, client override, and system FD limit.
197-
* Applies hysteresis to prevent rapid changes.
198-
*/
199-
static uint32_t s_get_dynamic_max_active_connections(
200-
struct aws_s3_client *client,
201-
struct aws_s3_meta_request *meta_request) {
202-
AWS_PRECONDITION(client);
203-
204-
/* Load sum of all meta request requirements */
205-
size_t total_size = aws_atomic_load_int(&client->stats.total_required_connections);
206-
207-
/* Overflow protection: Cap at uint32_t max if sum exceeds it */
208-
uint32_t total;
209-
if (total_size > UINT32_MAX) {
210-
total = UINT32_MAX;
211-
AWS_LOGF_WARN(
212-
AWS_LS_S3_CLIENT,
213-
"id=%p Total required connections (%zu) exceeds uint32_t max, capping at %u",
214-
(void *)client,
215-
total_size,
216-
UINT32_MAX);
217-
} else {
218-
total = (uint32_t)total_size;
219-
}
220-
221-
/* Handle zero case - keep minimum connections alive */
222-
if (total == 0) {
223-
return g_min_num_connections;
224-
}
225-
226-
/* Calculate new max connections value */
227-
uint32_t new_max = total;
228-
229-
/* Apply user's throughput-based override if set */
230-
if (client->max_active_connections_override > 0) {
231-
new_max = aws_min_u32(new_max, client->max_active_connections_override);
232-
}
233-
234-
/* respect meta request level overrides */
235-
if (meta_request && meta_request->max_active_connections_override > 0) {
236-
new_max = aws_min_u32(new_max, meta_request->max_active_connections_override);
237-
}
238-
239-
/* Apply system FD limit (checked dynamically) */
240-
uint32_t system_fd_limit = s_get_system_fd_limit();
241-
242-
/* Additional overflow protection: if system limit is 0 (getrlimit failed) */
243-
if (system_fd_limit == 0) {
244-
AWS_LOGF_WARN(
245-
AWS_LS_S3_CLIENT,
246-
"id=%p System FD limit query failed, using fallback value of %u",
247-
(void *)client,
248-
system_fd_limit);
249-
}
250-
251-
new_max = aws_min_u32(new_max, system_fd_limit);
252-
253-
/* Log warning if system limit is the bottleneck */
254-
if (new_max == system_fd_limit &&
255-
(total > system_fd_limit ||
256-
(client->max_active_connections_override > 0 && client->max_active_connections_override > system_fd_limit))) {
257-
AWS_LOGF_DEBUG(
258-
AWS_LS_S3_CLIENT,
259-
"id=%p Connection limit capped by system FD limit. "
260-
"Workload requires %u connections, config allows %u, but system limits to %u",
261-
(void *)client,
262-
total,
263-
client->max_active_connections_override > 0 ? client->max_active_connections_override : total,
264-
system_fd_limit);
265-
}
266-
267-
return new_max;
268-
}
269-
270194
/* Returns the max number of connections allowed.
271195
*
272196
* When meta request is NULL, this will return the overall allowed number of connections based on the clinet
@@ -280,16 +204,26 @@ uint32_t aws_s3_client_get_max_active_connections(
280204
struct aws_s3_meta_request *meta_request) {
281205
AWS_PRECONDITION(client);
282206

283-
/* Check feature flag - use dynamic scaling if enabled */
284-
if (client->enable_dynamic_connection_scaling) {
285-
return s_get_dynamic_max_active_connections(client, meta_request);
286-
}
287207
uint32_t max_active_connections = client->ideal_connection_count;
208+
209+
/* Respect total_required_connections calculated */
210+
size_t total_required = aws_atomic_load_int(&client->stats.total_required_connections);
211+
if (total_required > 0) {
212+
max_active_connections = aws_min_u32((uint32_t)total_required, max_active_connections);
213+
}
214+
215+
/* Respect user override */
288216
if (client->max_active_connections_override > 0 &&
289217
client->max_active_connections_override < max_active_connections) {
290218
max_active_connections = client->max_active_connections_override;
291219
}
220+
292221
if (meta_request) {
222+
/* Total number of connections for a meta request should not exceed number of parts */
223+
if (meta_request->object_size && meta_request->part_size) {
224+
max_active_connections =
225+
aws_min_u32(meta_request->object_size / meta_request->part_size, max_active_connections);
226+
}
293227
if (meta_request->max_active_connections_override) {
294228
/* Apply the meta request level override the max active connections, but less than the client side settings.
295229
*/
@@ -2331,7 +2265,7 @@ void aws_s3_client_update_connections_threaded(struct aws_s3_client *client) {
23312265

23322266
struct aws_s3_request *request = aws_s3_client_dequeue_request_threaded(client);
23332267
struct aws_s3_meta_request *meta_request = request->meta_request;
2334-
const uint32_t max_active_connections = aws_s3_client_get_max_active_connections(client, meta_request);
2268+
23352269
/* As the request removed from the queue. Decrement the preparing track */
23362270
--meta_request->client_process_work_threaded_data.num_request_being_prepared;
23372271
if (request->is_noop) {
@@ -2366,7 +2300,8 @@ void aws_s3_client_update_connections_threaded(struct aws_s3_client *client) {
23662300
/* Calculate: (meta_request->weight / client->total_weight) * 300 */
23672301
double weight_ratio = meta_request->weight / total_weight;
23682302
uint32_t allowed_connections = (uint32_t)(weight_ratio * client_max_active_connections);
2369-
2303+
const uint32_t max_active_connections =
2304+
aws_s3_client_get_max_active_connections(client, meta_request);
23702305
allowed_connections = aws_min_u32(allowed_connections, max_active_connections);
23712306

23722307
should_allocate_connection = (current_connections < allowed_connections);

source/s3_default_meta_request.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ struct aws_s3_meta_request *aws_s3_meta_request_default_new(
108108
}
109109

110110
meta_request_default->content_length = (size_t)content_length;
111+
/* copy content_length as object size.
112+
DISCLAIMER: content_length might be zero if object size is unknown. We might not always initialize it with some
113+
value. */
114+
meta_request_default->base.object_size = meta_request_default->content_length;
111115

112116
/* If request_type is unknown, look it up from operation name */
113117
if (request_type != AWS_S3_REQUEST_TYPE_UNKNOWN) {

source/s3_meta_request.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ static void s_validate_meta_request_checksum_on_finish(
164164
* Currently calculates based on: target_throughput / throughput_per_connection
165165
* Uses different throughput constants for S3 vs S3 Express.
166166
* TODO: Consider payload size, number of parts, and part size for more accurate calculation.
167-
* As part of this, this is the preliminary iteration where we take into account, the number of parts and part size.
167+
* This preliminary iteration is where we take into account, the number of parts and part size.
168168
* The distribution of connections uses something called a weight, a ratio of part_number / part_size.
169169
* we can use the same weight while providing the connections to provide more connections to the same sized object if
170170
* the number of parts is higher.
@@ -180,11 +180,11 @@ uint32_t s_calculate_meta_request_connections(struct aws_s3_client *client, stru
180180
/* Assuming 128MB part size provides the ideal throughput we expect after amortization, we find a ratio with the
181181
* current part size to find what the scaled throughput per connections would be. Logically, small for smaller part
182182
* sizes, larger for larger part sizes. */
183-
double scaling_factor = (meta_request->part_size > 0 ? ((GB_TO_BYTES(2) * 1.0) / meta_request->part_size) : 1);
183+
double scaling_factor = (meta_request->part_size > 0 ? ((MB_TO_BYTES(64) * 1.0) / meta_request->part_size) : 1);
184184

185185
/* Calculate connections needed: target_throughput / throughput_per_connection */
186186
double ideal_connections = client->throughput_target_gbps / throughput_per_connection;
187-
uint32_t required_connections = (uint32_t)ceil(ideal_connections) * scaling_factor;
187+
uint32_t required_connections = (uint32_t)ceil(ideal_connections * scaling_factor);
188188

189189
/* Clamp to reasonable range */
190190
if (required_connections < g_min_num_connections) {

0 commit comments

Comments
 (0)