blob: 98b64fd62e212b52d02a383d69a0c0010b714724 [file] [log] [blame] [edit]
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::str;
use std::time::{Duration, Instant};
extern crate linereader;
use linereader::LineReader;
extern crate memchr;
use memchr::Memchr;
const BUFFER_SIZE: usize = 1024 * 64;
struct Report {
lines: u64,
bytes: u64,
}
impl Report {
fn new(filename: &str) -> Self {
let mut infile = File::open(filename).expect("open");
let mut lines = 0_u64;
let mut bytes = 0_u64;
let mut buf = [0; BUFFER_SIZE];
while let Ok(r) = infile.read(&mut buf[..]) {
if r == 0 {
break;
}
bytes += r as u64;
lines += Memchr::new(b'\n', &buf[..r]).count() as u64;
}
println!("File: {}, bytes: {}, lines: {}", filename, bytes, lines);
println!(
"| {:16} | {:^7} | {:^11} | {:^13} |",
"Method", "Time", "Lines/sec", "Bandwidth"
);
println!("|------------------|--------:|------------:|--------------:|");
Self { lines, bytes }
}
fn report(&self, name: &str, bytes: Option<u64>, lines: Option<u64>, elapsed: Duration) {
if let Some(bytes) = bytes {
if bytes != self.bytes {
println!("Warning: expected {} bytes, read {}", self.bytes, bytes);
}
}
if let Some(lines) = lines {
if lines != self.lines {
println!("Warning: expected {} lines, read {}", self.lines, lines);
}
}
let elapsed =
(elapsed.as_secs() as f64) + (f64::from(elapsed.subsec_nanos()) / 1_000_000_000.0);
println!(
"| {:16} | {: >6.2}s | {:>9.0}/s | {:>8.2} MB/s |",
name,
elapsed,
(self.lines as f64) / elapsed,
((self.bytes as f64) / elapsed) / (1024.0 * 1024.0)
);
}
}
fn try_baseline(report: &Report, filename: &str) {
let mut infile = File::open(filename).expect("open");
let start = Instant::now();
let mut bytes = 0_u64;
let mut buf = [0; BUFFER_SIZE];
while let Ok(r) = infile.read(&mut buf[..]) {
if r == 0 {
break;
}
bytes += r as u64;
}
report.report("read()", Some(bytes), None, start.elapsed());
}
fn try_linereader_batch(report: &Report, filename: &str) {
let infile = File::open(filename).expect("open");
let mut reader = LineReader::with_capacity(BUFFER_SIZE, infile);
let start = Instant::now();
let mut bytes = 0_u64;
while let Some(batch) = reader.next_batch() {
let batch = batch.unwrap();
bytes += batch.len() as u64;
}
report.report("LR::next_batch()", Some(bytes), None, start.elapsed());
}
fn try_linereader(report: &Report, filename: &str) {
let infile = File::open(filename).expect("open");
let mut reader = LineReader::with_capacity(BUFFER_SIZE, infile);
let start = Instant::now();
let mut lines = 0_u64;
let mut bytes = 0_u64;
while let Some(line) = reader.next_line() {
bytes += line.unwrap().len() as u64;
lines += 1;
}
report.report("LR::next_line()", Some(bytes), Some(lines), start.elapsed());
}
fn try_read_until(report: &Report, filename: &str) {
let infile = File::open(filename).expect("open");
let mut infile = BufReader::with_capacity(BUFFER_SIZE, infile);
let start = Instant::now();
let mut lines = 0_u64;
let mut bytes = 0_u64;
let mut line: Vec<u8> = Vec::with_capacity(128);
while infile.read_until(b'\n', &mut line).unwrap_or(0) > 0 {
bytes += line.len() as u64;
lines += 1;
line.clear();
}
report.report("read_until()", Some(bytes), Some(lines), start.elapsed());
}
fn try_read_line(report: &Report, filename: &str) {
let infile = File::open(filename).expect("open");
let mut infile = BufReader::with_capacity(BUFFER_SIZE, infile);
let start = Instant::now();
let mut lines = 0_u64;
let mut bytes = 0_u64;
let mut line = String::new();
while infile.read_line(&mut line).unwrap_or(0) > 0 {
bytes += line.len() as u64;
lines += 1;
line.clear();
}
report.report("read_line()", Some(bytes), Some(lines), start.elapsed());
}
fn try_lines_iter(report: &Report, filename: &str) {
let infile = File::open(filename).expect("open");
let infile = BufReader::with_capacity(BUFFER_SIZE, infile);
let start = Instant::now();
let mut lines = 0_u64;
for _line in infile.lines() {
lines += 1;
}
report.report("lines()", None, Some(lines), start.elapsed());
}
fn main() {
use std::env;
for file in env::args().skip(1) {
let report = Report::new(&file);
try_baseline(&report, &file);
try_linereader_batch(&report, &file);
try_linereader(&report, &file);
try_read_until(&report, &file);
try_read_line(&report, &file);
try_lines_iter(&report, &file);
}
}