4545
4646struct aws_s3_default_buffer_pool ;
4747
48+ enum aws_s3_default_buffer_pool_reserved_from {
49+ AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY ,
50+ AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY ,
51+ AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL ,
52+ };
53+
4854struct aws_s3_default_buffer_ticket {
4955 size_t size ;
5056 uint8_t * ptr ;
5157 size_t chunks_used ;
5258 bool forced ;
5359 struct aws_s3_buffer_pool * pool ;
5460 bool is_special_block ; /* True if this ticket is from a special-sized block */
61+ enum aws_s3_default_buffer_pool_reserved_from reserved_from /* which area ticket was reserved from */
5562};
5663
5764/* Default size for blocks array. Note: this is just for meta info, blocks
@@ -82,6 +89,12 @@ static const size_t s_max_chunk_size_for_buffer_reuse = MB_TO_BYTES(64);
8289 * we still consider 1GiB available for normal buffer usage. */
8390static const size_t s_max_impact_of_forced_buffers_on_memory_limit_as_percentage = 80 ;
8491
92+ /*
93+ * primary min cut off. below this number buffers are not allocated from primary and instead use
94+ * secondary.
95+ */
96+ static const size_t s_primary_min_cutoff = KB_TO_BYTES (128 );
97+
8598/*
8699 * Sets n bits at position starting with LSB.
87100 * Note: n must be at most 8, but in practice will always be at most 4.
@@ -232,6 +245,18 @@ struct aws_s3_buffer_pool *aws_s3_default_buffer_pool_new(
232245 chunk_size = 0 ;
233246 }
234247
248+ /*
249+ * This is fairly arbitrary. System allocator tends to be a bit better on tiny allocations.
250+ * And we want to avoid wasting mem in that case.
251+ * Note this is not the answer for wasting mem, but it does improve some corner cases.
252+ */
253+ size_t min_primary_size = 0 ;
254+ if (4 * chunk_size >= s_primary_min_cutoff ) {
255+ min_primary_size = s_primary_min_cutoff ;
256+ } else {
257+ min_primary_size = 0 ;
258+ }
259+
235260 size_t page_size = aws_system_info_page_size ();
236261 /* TODO: if people override their allocator, this will not wrap their allocator at all. eg: mem-tracing allocator
237262 * will be ignored. */
@@ -248,6 +273,7 @@ struct aws_s3_buffer_pool *aws_s3_default_buffer_pool_new(
248273 * Tries to balance between how many allocations use buffer and buffer space
249274 * being wasted. */
250275 buffer_pool -> primary_size_cutoff = chunk_size * 4 ;
276+ buffer_pool -> primary_size_min_cutoff = min_primary_size ;
251277 buffer_pool -> mem_limit = adjusted_mem_lim ;
252278
253279 int mutex_error = aws_mutex_init (& buffer_pool -> mutex );
@@ -395,16 +421,18 @@ static void s_aws_ticket_wrapper_destroy(void *data) {
395421
396422 if (ticket -> ptr == NULL ) {
397423 /* Ticket was never used, make sure to clean up reserved count. */
398- if (ticket -> is_special_block ) {
424+ if (ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL ) {
399425 buffer_pool -> special_blocks_reserved -= ticket -> size ;
400- } else if (ticket -> size <= buffer_pool -> primary_size_cutoff ) {
426+ } else if (ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY ) {
401427 buffer_pool -> primary_reserved -= ticket -> size ;
402- } else {
428+ } else if ( ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY ) {
403429 buffer_pool -> secondary_reserved -= ticket -> size ;
430+ } else {
431+ AWS_ASSERT (false); /* someone forgot to update this after adding new member. */
404432 }
405433 } else {
406434 /* Handle special block returns */
407- if (ticket -> is_special_block ) {
435+ if (ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL ) {
408436 struct aws_hash_element * elem = NULL ;
409437 aws_hash_table_find (& buffer_pool -> special_blocks , (void * )ticket -> size , & elem );
410438 /* TODO: the lifetime between the ticket and the special block, let's assume the block will always be
@@ -427,7 +455,7 @@ static void s_aws_ticket_wrapper_destroy(void *data) {
427455 /* Make sure we do find where the ticket buffer from the list. */
428456 AWS_FATAL_ASSERT (found );
429457 buffer_pool -> special_blocks_used -= ticket -> size ;
430- } else if (ticket -> size <= buffer_pool -> primary_size_cutoff ) {
458+ } else if (ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY ) {
431459
432460 size_t chunks_used = ticket -> size / buffer_pool -> chunk_size ;
433461 if (ticket -> size % buffer_pool -> chunk_size != 0 ) {
@@ -455,13 +483,15 @@ static void s_aws_ticket_wrapper_destroy(void *data) {
455483 if (ticket -> forced ) {
456484 buffer_pool -> forced_used -= ticket -> size ;
457485 }
458- } else {
486+ } else if ( ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY ) {
459487 aws_mem_release (buffer_pool -> base_allocator , ticket -> ptr );
460488 buffer_pool -> secondary_used -= ticket -> size ;
461489
462490 if (ticket -> forced ) {
463491 buffer_pool -> forced_used -= ticket -> size ;
464492 }
493+ } else {
494+ AWS_ASSERT (false); /* someone forgot to update this after adding new member. */
465495 }
466496 }
467497 aws_mem_release (buffer_pool -> base_allocator , ticket );
@@ -609,10 +639,18 @@ struct aws_s3_default_buffer_ticket *s_try_reserve_synced(
609639 /* Check if this is a special-sized allocation */
610640 if (from_special ) {
611641 ticket -> is_special_block = true;
642+ ticket -> reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL ;
612643 buffer_pool -> special_blocks_reserved += meta .size ;
613- } else if (meta .size <= buffer_pool -> primary_size_cutoff ) {
614- buffer_pool -> primary_reserved += meta .size ;
644+ } else if (meta .size <= buffer_pool -> primary_size_cutoff ) { /* TODO: this needs to be smarter. what if block size more than mem_lim*/
645+ if (meta .size <= buffer_pool -> primary_size_min_cutoff ) {
646+ ticket -> reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY ;
647+ buffer_pool -> secondary_reserved += meta .size ;
648+ } else {
649+ ticket -> reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY ;
650+ buffer_pool -> primary_reserved += meta .size ;
651+ }
615652 } else {
653+ ticket -> reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY ;
616654 buffer_pool -> secondary_reserved += meta .size ;
617655 }
618656 }
0 commit comments