@@ -524,7 +524,9 @@ void RedisReplyBuilder::SendStringArr(StrSpan arr, CollectionType type) {
524
524
return ;
525
525
}
526
526
527
- SendStringArrInternal (warr, type);
527
+ auto cb = [&](size_t i) { return warr[i]; };
528
+
529
+ SendStringArrInternal (warr.Size (), std::move (cb), type);
528
530
}
529
531
530
532
void RedisReplyBuilder::StartArray (unsigned len) {
@@ -558,9 +560,8 @@ void RedisReplyBuilder::StartCollection(unsigned len, CollectionType type) {
558
560
// to low numbers (around 1024). Therefore, to make it robust we send the array in batches.
559
561
// We limit the vector length to 256 and when it fills up we flush it to the socket and continue
560
562
// iterating.
561
- void RedisReplyBuilder::SendStringArrInternal (WrappedStrSpan arr, CollectionType type) {
562
- size_t size = arr.Size ();
563
-
563
+ void RedisReplyBuilder::SendStringArrInternal (
564
+ size_t size, absl::FunctionRef<std::string_view(unsigned )> producer, CollectionType type) {
564
565
size_t header_len = size;
565
566
string_view type_char = " *" ;
566
567
if (is_resp3_) {
@@ -575,40 +576,41 @@ void RedisReplyBuilder::SendStringArrInternal(WrappedStrSpan arr, CollectionType
575
576
}
576
577
577
578
// When vector length is too long, Send returns EMSGSIZE.
578
- size_t vec_len = std::min<size_t >(256u , size);
579
+ size_t vec_len = std::min<size_t >(128u , size);
579
580
580
581
absl::FixedArray<iovec, 16 > vec (vec_len * 2 + 2 );
581
- absl::FixedArray<char , 64 > meta ((vec_len + 1 ) * 16 );
582
+ absl::FixedArray<char , 64 > meta ((vec_len + 1 ) * 16 ); // 16 bytes per length.
582
583
char * next = meta.data ();
583
584
584
- *next++ = type_char[0 ];
585
- next = absl::numbers_internal::FastIntToBuffer (header_len, next);
586
- *next++ = ' \r ' ;
587
- *next++ = ' \n ' ;
585
+ auto serialize_len = [&](char prefix, size_t len) {
586
+ *next++ = prefix;
587
+ next = absl::numbers_internal::FastIntToBuffer (len, next);
588
+ *next++ = ' \r ' ;
589
+ *next++ = ' \n ' ;
590
+ };
591
+
592
+ serialize_len (type_char[0 ], header_len);
588
593
vec[0 ] = IoVec (string_view{meta.data (), size_t (next - meta.data ())});
589
594
char * start = next;
590
595
591
596
unsigned vec_indx = 1 ;
592
597
string_view src;
593
598
for (unsigned i = 0 ; i < size; ++i) {
594
- src = arr[i];
595
- *next++ = ' $' ;
596
- next = absl::numbers_internal::FastIntToBuffer (src.size (), next);
597
- *next++ = ' \r ' ;
598
- *next++ = ' \n ' ;
599
- vec[vec_indx] = IoVec (string_view{start, size_t (next - start)});
599
+ src = producer (i);
600
+ serialize_len (' $' , src.size ());
601
+ // add serialized len blob
602
+ vec[vec_indx++] = IoVec (string_view{start, size_t (next - start)});
600
603
DCHECK_GT (next - start, 0 );
601
604
602
605
start = next;
603
- ++vec_indx;
604
606
605
- vec[vec_indx] = IoVec (src);
607
+ vec[vec_indx++ ] = IoVec (src);
606
608
607
609
*next++ = ' \r ' ;
608
610
*next++ = ' \n ' ;
609
- ++vec_indx;
610
611
611
612
if (vec_indx + 1 >= vec.size ()) {
613
+ // Flush the iovec array.
612
614
if (i < size - 1 || vec_indx == vec.size ()) {
613
615
Send (vec.data (), vec_indx);
614
616
if (ec_)
0 commit comments