@@ -349,19 +349,26 @@ impl<W: Write> BufWriter<W> {
349
349
// Ensure this function does not get inlined into `write`, so that it
350
350
// remains inlineable and its common path remains as short as possible.
351
351
// 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.
353
354
#[ 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
+ }
356
359
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.
359
362
if buf. len ( ) >= self . buf . capacity ( ) {
360
363
self . panicked = true ;
361
364
let r = self . get_mut ( ) . write ( buf) ;
362
365
self . panicked = false ;
363
366
r
364
367
} 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
+
365
372
// SAFETY: We just called `self.flush_buf()`, so `self.buf.len()` is 0, and
366
373
// we entered this else block because `buf.len() < self.buf.capacity()`.
367
374
// Therefore, `self.buf.len() + buf.len() <= self.buf.capacity()`.
@@ -376,23 +383,30 @@ impl<W: Write> BufWriter<W> {
376
383
// Ensure this function does not get inlined into `write_all`, so that it
377
384
// remains inlineable and its common path remains as short as possible.
378
385
// 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.
380
388
#[ 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 < ( ) > {
382
390
// Normally, `write_all` just calls `write` in a loop. We can do better
383
391
// by calling `self.get_mut().write_all()` directly, which avoids
384
392
// round trips through the buffer in the event of a series of partial
385
393
// writes in some circumstances.
386
- self . flush_buf ( ) ?;
394
+ if self . buf . len ( ) + buf. len ( ) > self . buf . capacity ( ) {
395
+ self . flush_buf ( ) ?;
396
+ }
387
397
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.
390
400
if buf. len ( ) >= self . buf . capacity ( ) {
391
401
self . panicked = true ;
392
402
let r = self . get_mut ( ) . write_all ( buf) ;
393
403
self . panicked = false ;
394
404
r
395
405
} 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
+
396
410
// SAFETY: We just called `self.flush_buf()`, so `self.buf.len()` is 0, and
397
411
// we entered this else block because `buf.len() < self.buf.capacity()`.
398
412
// Therefore, `self.buf.len() + buf.len() <= self.buf.capacity()`.
@@ -489,39 +503,33 @@ impl fmt::Debug for WriterPanicked {
489
503
impl < W : Write > Write for BufWriter < W > {
490
504
#[ inline]
491
505
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 ( ) {
498
509
// SAFETY: safe by above conditional.
499
510
unsafe {
500
511
self . write_to_buffer_unchecked ( buf) ;
501
512
}
502
513
503
514
Ok ( buf. len ( ) )
504
515
} else {
505
- self . flush_and_write ( buf)
516
+ self . write_cold ( buf)
506
517
}
507
518
}
508
519
509
520
#[ inline]
510
521
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 ( ) {
517
525
// SAFETY: safe by above conditional.
518
526
unsafe {
519
527
self . write_to_buffer_unchecked ( buf) ;
520
528
}
521
529
522
530
Ok ( ( ) )
523
531
} else {
524
- self . flush_and_write_all ( buf)
532
+ self . write_all_cold ( buf)
525
533
}
526
534
}
527
535
0 commit comments