Repository: TeXitoi/benchmarksgame-rs (language: rust)

Issue:
reverse_complement spends most of its time reading input
On my system, `reverse_complement < input25000000.txt` spends 67% of its time on the `read_to_end` call here.  According to the profile, that time is almost all spent in `memmove`.

```rust
    let mut data = Vec::with_capacity(1024 * 1024);
    stdin.lock().read_to_end(&mut data).unwrap();
```

Increasing the initial buffer size to fit the entire dataset cuts the `read_to_end` time in half, and reduces the total execution time by about 30%, but obviously it also wastes memory if the data is small.  (Since this program reads from stdin, it doesn't known the total size before it starts reading.)


Discussion / hints:
The C++ code uses `ftell` to get the input size before allocating a buffer:

```cpp
      long start = ftell( stdin );
      fseek( stdin, 0, SEEK_END );
      size = ftell( stdin ) - start;
```

Fix patch:
diff --git a/src/reverse_complement.rs b/src/reverse_complement.rs
index ef84eac..88ce01e 100644
--- a/src/reverse_complement.rs
+++ b/src/reverse_complement.rs
@@ -2,6 +2,7 @@
 // http://benchmarksgame.alioth.debian.org/
 //
 // contributed by the Rust Project Developers
+// contributed by Matt Brubeck
 // contributed by TeXitoi
 
 //extern crate libc;
@@ -20,6 +21,8 @@ mod libc {
 use std::io::{Read, Write};
 use std::ptr::copy;
 use std::thread;
+use std::fs::File;
+use std::os::unix::io::FromRawFd;
 
 struct Tables {
     table8: [u8;1 << 8],
@@ -187,10 +190,15 @@ fn parallel<'a, I, T, F>(iter: I, ref f: F)
     for jh in jhs { jh.join().unwrap(); }
 }
 
+fn file_size(f: &mut File) -> std::io::Result<usize> {
+    Ok(f.metadata()?.len() as usize)
+}
+
 fn main() {
-    let stdin = std::io::stdin();
-    let mut data = Vec::with_capacity(1024 * 1024);
-    stdin.lock().read_to_end(&mut data).unwrap();
+    let mut stdin = unsafe { File::from_raw_fd(0) };
+    let size = file_size(&mut stdin).unwrap_or(1024 * 1024);
+    let mut data = Vec::with_capacity(size + 1);
+    stdin.read_to_end(&mut data).unwrap();
     let tables = &Tables::new();
     parallel(mut_dna_seqs(&mut data), |seq| reverse_complement(seq, tables));
     let stdout = std::io::stdout();


Test patch: