@@ -349,19 +349,26 @@ impl<W: Write> BufWriter<W> {
349349 // Ensure this function does not get inlined into `write`, so that it
350350 // remains inlineable and its common path remains as short as possible.
351351 // If this function ends up being called frequently relative to `write`,
352- // it's likely a sign that the client is using an improperly sized buffer.
352+ // it's likely a sign that the client is using an improperly sized buffer
353+ // or their write patterns are somewhat pathological.
353354 #[ inline( never) ]
354- fn flush_and_write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
355- self . flush_buf ( ) ?;
355+ fn write_cold ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
356+ if self . buf . len ( ) + buf. len ( ) > self . buf . capacity ( ) {
357+ self . flush_buf ( ) ?;
358+ }
356359
357- // Why not len > capacity? To avoid a needless trip through the buffer when the
358- // input exactly fills. We'd just need to flush it to the underlying writer anyway.
360+ // Why not len > capacity? To avoid a needless trip through the buffer when the input
361+ // exactly fills it . We'd just need to flush it to the underlying writer anyway.
359362 if buf. len ( ) >= self . buf . capacity ( ) {
360363 self . panicked = true ;
361364 let r = self . get_mut ( ) . write ( buf) ;
362365 self . panicked = false ;
363366 r
364367 } else {
368+ // Write to the buffer. In this case, we write to the buffer even if it fills it
369+ // exactly. Doing otherwise would mean flushing the buffer, then writing this
370+ // input to the inner writer, which in many cases would be a worse strategy.
371+
365372 // SAFETY: We just called `self.flush_buf()`, so `self.buf.len()` is 0, and
366373 // we entered this else block because `buf.len() < self.buf.capacity()`.
367374 // Therefore, `self.buf.len() + buf.len() <= self.buf.capacity()`.
@@ -376,23 +383,30 @@ impl<W: Write> BufWriter<W> {
376383 // Ensure this function does not get inlined into `write_all`, so that it
377384 // remains inlineable and its common path remains as short as possible.
378385 // If this function ends up being called frequently relative to `write_all`,
379- // it's likely a sign that the client is using an improperly sized buffer.
386+ // it's likely a sign that the client is using an improperly sized buffer
387+ // or their write patterns are somewhat pathological.
380388 #[ inline( never) ]
381- fn flush_and_write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
389+ fn write_all_cold ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
382390 // Normally, `write_all` just calls `write` in a loop. We can do better
383391 // by calling `self.get_mut().write_all()` directly, which avoids
384392 // round trips through the buffer in the event of a series of partial
385393 // writes in some circumstances.
386- self . flush_buf ( ) ?;
394+ if self . buf . len ( ) + buf. len ( ) > self . buf . capacity ( ) {
395+ self . flush_buf ( ) ?;
396+ }
387397
388- // Why not len > capacity? To avoid a needless trip through the buffer when the
389- // input exactly fills. We'd just need to flush it to the underlying writer anyway.
398+ // Why not len > capacity? To avoid a needless trip through the buffer when the input
399+ // exactly fills it . We'd just need to flush it to the underlying writer anyway.
390400 if buf. len ( ) >= self . buf . capacity ( ) {
391401 self . panicked = true ;
392402 let r = self . get_mut ( ) . write_all ( buf) ;
393403 self . panicked = false ;
394404 r
395405 } else {
406+ // Write to the buffer. In this case, we write to the buffer even if it fills it
407+ // exactly. Doing otherwise would mean flushing the buffer, then writing this
408+ // input to the inner writer, which in many cases would be a worse strategy.
409+
396410 // SAFETY: We just called `self.flush_buf()`, so `self.buf.len()` is 0, and
397411 // we entered this else block because `buf.len() < self.buf.capacity()`.
398412 // Therefore, `self.buf.len() + buf.len() <= self.buf.capacity()`.
@@ -489,39 +503,33 @@ impl fmt::Debug for WriterPanicked {
489503impl < W : Write > Write for BufWriter < W > {
490504 #[ inline]
491505 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
492- // The `buf.len() != self.buf.capacity()` check is done to avoid a needless trip through
493- // the buffer when the input is exactly the same size as it. For many clients, that is a
494- // rare event, so it's unfortunate that the check is in the common code path. But it
495- // prevents pathological cases for other clients which *always* make writes of this size.
496- // See #72919 and #79930 for more info and a breadcrumb trail.
497- if self . buf . len ( ) + buf. len ( ) <= self . buf . capacity ( ) && buf. len ( ) != self . buf . capacity ( ) {
506+ // Use < instead of <= to avoid a needless trip through the buffer in some cases.
507+ // See `write_cold` for details.
508+ if self . buf . len ( ) + buf. len ( ) < self . buf . capacity ( ) {
498509 // SAFETY: safe by above conditional.
499510 unsafe {
500511 self . write_to_buffer_unchecked ( buf) ;
501512 }
502513
503514 Ok ( buf. len ( ) )
504515 } else {
505- self . flush_and_write ( buf)
516+ self . write_cold ( buf)
506517 }
507518 }
508519
509520 #[ inline]
510521 fn write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
511- // The `buf.len() != self.buf.capacity()` check is done to avoid a needless trip through
512- // the buffer when the input is exactly the same size as it. For many clients, that is a
513- // rare event, so it's unfortunate that the check is in the common code path. But it
514- // prevents pathological cases for other clients which *always* make writes of this size.
515- // See #72919 and #79930 for more info and a breadcrumb trail.
516- if self . buf . len ( ) + buf. len ( ) <= self . buf . capacity ( ) && buf. len ( ) != self . buf . capacity ( ) {
522+ // Use < instead of <= to avoid a needless trip through the buffer in some cases.
523+ // See `write_all_cold` for details.
524+ if self . buf . len ( ) + buf. len ( ) < self . buf . capacity ( ) {
517525 // SAFETY: safe by above conditional.
518526 unsafe {
519527 self . write_to_buffer_unchecked ( buf) ;
520528 }
521529
522530 Ok ( ( ) )
523531 } else {
524- self . flush_and_write_all ( buf)
532+ self . write_all_cold ( buf)
525533 }
526534 }
527535
0 commit comments