Skip to content

Instantly share code, notes, and snippets.

@sethdusek
Created July 14, 2017 17:06
Show Gist options
  • Save sethdusek/430e3bfa05a802c3a2501dc0564edda6 to your computer and use it in GitHub Desktop.
Save sethdusek/430e3bfa05a802c3a2501dc0564edda6 to your computer and use it in GitHub Desktop.
extern crate libc;
pub mod zc;
#![feature(test)]
extern crate test;
extern crate zerocopy;
use zerocopy::zc::ZeroCopy;
use test::Bencher;
use std::io::prelude::*;
use std::fs::File;
#[bench]
fn zerocopy(b: &mut Bencher) {
let mut src = File::open("/tmp/foo").unwrap();
let mut dest = File::create("/tmp/foo.txt").unwrap();
b.iter(|| {
unsafe { src.copy_to_fd(&mut dest).unwrap() };
});
std::fs::remove_file("/tmp/foo.txt");
}
#[bench]
fn default(b: &mut Bencher) {
let mut src = File::open("/tmp/foo").unwrap();
let mut dest = File::create("/tmp/foo.txt").unwrap();
let len = src.metadata().unwrap().len() as usize;
b.iter(|| {
::std::io::copy(&mut src, &mut dest).unwrap();
src.seek(::std::io::SeekFrom::Start(0));
});
std::fs::remove_file("/tmp/foo.txt");
}
use libc::{c_int, splice};
use std::os::unix::io::AsRawFd;
use std::io::Result;
use std::io::prelude::*;
const __NR_copy_file_range: ::libc::c_long = 326;
unsafe fn copy_file_range(fd_in: c_int, off_in: *mut ::libc::loff_t, fd_out: c_int, off_out: *mut ::libc::loff_t, len: usize, flags: u32) -> i64 {
::libc::syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags)
}
pub trait ZeroCopy<T> {
unsafe fn copy_to_fd(&mut self, fd: &mut T) -> Result<u64>;
}
/*impl <T> ZeroCopy for T where T: AsRawFd + Read {
unsafe fn copy_to_fd<FD: AsRawFd + Write>(&mut self, fd: &mut FD) -> Result<u64> {
let res = splice(0, ::std::ptr::null_mut(), fd.as_raw_fd(), ::std::ptr::null_mut(), 12, 0);
Ok(res as u64)
}
}*/
impl ZeroCopy<::std::fs::File> for ::std::fs::File {
unsafe fn copy_to_fd(&mut self, fd: &mut ::std::fs::File) -> Result<u64> {
let len = fd.metadata()?.len() as usize;
let bytes = copy_file_range(self.as_raw_fd(), ::std::ptr::null_mut(), fd.as_raw_fd(), ::std::ptr::null_mut(), len, 0);
if bytes < 0 {
Err(::std::io::Error::last_os_error())
}
else { Ok(bytes as u64) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment