|
1 | 1 | use super::{repeat, Cursor, SeekFrom};
|
2 | 2 | use crate::cmp::{self, min};
|
| 3 | +use crate::env::temp_dir; |
| 4 | +#[cfg(unix)] |
| 5 | +use crate::fs::OpenOptions; |
| 6 | +#[cfg(unix)] |
| 7 | +use crate::io::Result; |
3 | 8 | use crate::io::{self, IoSlice, IoSliceMut};
|
4 |
| -use crate::io::{BufRead, BufReader, BufWriter, Read, Result, Seek, Write}; |
| 9 | +use crate::io::{BufRead, Read, Seek, Write}; |
5 | 10 | use crate::ops::Deref;
|
| 11 | +#[cfg(unix)] |
| 12 | +use crate::os::unix::io::AsRawFd; |
6 | 13 |
|
7 | 14 | #[test]
|
8 | 15 | #[cfg_attr(target_os = "emscripten", ignore)]
|
@@ -496,6 +503,8 @@ fn test_write_all_vectored() {
|
496 | 503 | #[test]
|
497 | 504 | #[cfg(unix)]
|
498 | 505 | fn copy_specialization() -> Result<()> {
|
| 506 | + use crate::io::{BufReader, BufWriter}; |
| 507 | + |
499 | 508 | let path = crate::env::temp_dir();
|
500 | 509 | let source_path = path.join("copy-spec.source");
|
501 | 510 | let sink_path = path.join("copy-spec.sink");
|
@@ -543,3 +552,124 @@ fn copy_specialization() -> Result<()> {
|
543 | 552 |
|
544 | 553 | result.and(rm1).and(rm2)
|
545 | 554 | }
|
| 555 | + |
| 556 | +#[bench] |
| 557 | +fn bench_file_to_file_copy(b: &mut test::Bencher) { |
| 558 | + const BYTES: usize = 128 * 1024; |
| 559 | + let src_path = temp_dir().join("file-copy-bench-src"); |
| 560 | + let mut src = crate::fs::OpenOptions::new() |
| 561 | + .create(true) |
| 562 | + .truncate(true) |
| 563 | + .read(true) |
| 564 | + .write(true) |
| 565 | + .open(src_path) |
| 566 | + .unwrap(); |
| 567 | + src.write(&vec![0u8; BYTES]).unwrap(); |
| 568 | + |
| 569 | + let sink_path = temp_dir().join("file-copy-bench-sink"); |
| 570 | + let mut sink = crate::fs::OpenOptions::new() |
| 571 | + .create(true) |
| 572 | + .truncate(true) |
| 573 | + .write(true) |
| 574 | + .open(sink_path) |
| 575 | + .unwrap(); |
| 576 | + |
| 577 | + b.bytes = BYTES as u64; |
| 578 | + b.iter(|| { |
| 579 | + src.seek(SeekFrom::Start(0)).unwrap(); |
| 580 | + sink.seek(SeekFrom::Start(0)).unwrap(); |
| 581 | + assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap()); |
| 582 | + }); |
| 583 | +} |
| 584 | + |
| 585 | +#[cfg(unix)] |
| 586 | +#[bench] |
| 587 | +fn bench_file_to_socket_copy(b: &mut test::Bencher) { |
| 588 | + const BYTES: usize = 128 * 1024; |
| 589 | + let src_path = temp_dir().join("pipe-copy-bench-src"); |
| 590 | + let mut src = OpenOptions::new() |
| 591 | + .create(true) |
| 592 | + .truncate(true) |
| 593 | + .read(true) |
| 594 | + .write(true) |
| 595 | + .open(src_path) |
| 596 | + .unwrap(); |
| 597 | + src.write(&vec![0u8; BYTES]).unwrap(); |
| 598 | + |
| 599 | + let sink_drainer = crate::net::TcpListener::bind("localhost:0").unwrap(); |
| 600 | + let mut sink = crate::net::TcpStream::connect(sink_drainer.local_addr().unwrap()).unwrap(); |
| 601 | + let mut sink_drainer = sink_drainer.accept().unwrap().0; |
| 602 | + |
| 603 | + crate::thread::spawn(move || { |
| 604 | + let mut sink_buf = vec![0u8; 1024 * 1024]; |
| 605 | + loop { |
| 606 | + sink_drainer.read(&mut sink_buf[..]).unwrap(); |
| 607 | + } |
| 608 | + }); |
| 609 | + |
| 610 | + b.bytes = BYTES as u64; |
| 611 | + b.iter(|| { |
| 612 | + src.seek(SeekFrom::Start(0)).unwrap(); |
| 613 | + assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap()); |
| 614 | + }); |
| 615 | +} |
| 616 | + |
| 617 | +#[cfg(any(target_os = "linux", target_os = "android"))] |
| 618 | +#[bench] |
| 619 | +fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) { |
| 620 | + use crate::io::ErrorKind; |
| 621 | + use crate::process::{ChildStdin, ChildStdout}; |
| 622 | + use crate::sys_common::FromInner; |
| 623 | + |
| 624 | + let (read_end, write_end) = crate::sys::pipe::anon_pipe().unwrap(); |
| 625 | + |
| 626 | + let mut read_end = ChildStdout::from_inner(read_end); |
| 627 | + let write_end = ChildStdin::from_inner(write_end); |
| 628 | + |
| 629 | + let acceptor = crate::net::TcpListener::bind("localhost:0").unwrap(); |
| 630 | + let mut remote_end = crate::net::TcpStream::connect(acceptor.local_addr().unwrap()).unwrap(); |
| 631 | + |
| 632 | + let local_end = crate::sync::Arc::new(acceptor.accept().unwrap().0); |
| 633 | + |
| 634 | + crate::thread::spawn(move || { |
| 635 | + let mut sink_buf = vec![0u8; 1024 * 1024]; |
| 636 | + remote_end.set_nonblocking(true).unwrap(); |
| 637 | + loop { |
| 638 | + match remote_end.write(&mut sink_buf[..]) { |
| 639 | + Err(err) if err.kind() == ErrorKind::WouldBlock => {} |
| 640 | + Ok(_) => {} |
| 641 | + err => { |
| 642 | + err.expect("write failed"); |
| 643 | + } |
| 644 | + }; |
| 645 | + match remote_end.read(&mut sink_buf[..]) { |
| 646 | + Err(err) if err.kind() == ErrorKind::WouldBlock => {} |
| 647 | + Ok(_) => {} |
| 648 | + err => { |
| 649 | + err.expect("read failed"); |
| 650 | + } |
| 651 | + }; |
| 652 | + } |
| 653 | + }); |
| 654 | + |
| 655 | + let local_source = local_end.clone(); |
| 656 | + crate::thread::spawn(move || { |
| 657 | + loop { |
| 658 | + crate::sys::fs::sendfile_splice( |
| 659 | + crate::sys::fs::SpliceMode::Splice, |
| 660 | + local_source.as_raw_fd(), |
| 661 | + write_end.as_raw_fd(), |
| 662 | + u64::MAX, |
| 663 | + ); |
| 664 | + } |
| 665 | + }); |
| 666 | + |
| 667 | + const BYTES: usize = 128 * 1024; |
| 668 | + b.bytes = BYTES as u64; |
| 669 | + b.iter(|| { |
| 670 | + assert_eq!( |
| 671 | + BYTES as u64, |
| 672 | + io::copy(&mut (&mut read_end).take(BYTES as u64), &mut &*local_end).unwrap() |
| 673 | + ); |
| 674 | + }); |
| 675 | +} |
0 commit comments