Skip to content
This repository has been archived by the owner on Jul 11, 2019. It is now read-only.

Commit

Permalink
Swap internal numtoa module for external numtoa crate
Browse files Browse the repository at this point in the history
- I've spun the `numtoa` module off into a new crate
- The new crate contains more performance optimizations
- The `numtoa` crate has the same performance as the `itoa` crate
- Integer conversions have never been better
  • Loading branch information
mmstick committed Jan 17, 2017
1 parent d71d0f6 commit 776dbca
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 235 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ readme = "README.md"

[dependencies]
itoa = "0.1"
numtoa = "0.0.3"
num_cpus = "1.2"
permutate = "0.2"
arrayvec = "0.3"
Expand Down
10 changes: 5 additions & 5 deletions src/execute/dry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use input_iterator::{InputIterator, InputIteratorErr};
use tokenizer::Token;
use arguments;
use execute::command;
use misc::NumToA;
use numtoa::NumToA;

use std::io::{self, StdoutLock, Write};

Expand All @@ -18,8 +18,8 @@ pub fn dry_run(flags: u16, inputs: InputIterator, arguments: &[Token]) {
let pipe = flags & arguments::PIPE_IS_ENABLED != 0;
let mut id_buffer = [0u8; 20];
let mut total_buffer = [0u8; 20];
let truncate = inputs.total_arguments.numtoa(10, &mut total_buffer);
let job_total = &total_buffer[0..truncate];
let start_indice = inputs.total_arguments.numtoa(10, &mut total_buffer);
let job_total = &total_buffer[start_indice..];

// If `SHELL_QUOTE` is enabled then the quoted command will be printed, otherwise the command will be
// printed unmodified. The correct function to execute will be assigned here in advance.
Expand All @@ -40,10 +40,10 @@ pub fn dry_run(flags: u16, inputs: InputIterator, arguments: &[Token]) {
for (job_id, input) in inputs.enumerate() {
match input {
Ok(input) => {
let truncate = job_id.numtoa(10, &mut id_buffer);
let start_indice = job_id.numtoa(10, &mut id_buffer);
let command = command::ParallelCommand {
slot_no: slot,
job_no: &id_buffer[0..truncate],
job_no: &id_buffer[start_indice..],
job_total: job_total,
input: &input,
command_template: arguments,
Expand Down
10 changes: 5 additions & 5 deletions src/execute/exec_commands.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use arguments::{VERBOSE_MODE, JOBLOG};
use execute::command::{self, CommandErr};
use input_iterator::InputsLock;
use misc::NumToA;
use numtoa::NumToA;
use time::{self, Timespec};
use tokenizer::Token;
use verbose;
Expand Down Expand Up @@ -39,19 +39,19 @@ impl ExecCommands {
let mut id_buffer = [0u8; 20];
let mut job_buffer = [0u8; 20];
let mut total_buffer = [0u8; 20];
let truncate = self.num_inputs.numtoa(10, &mut total_buffer);
let job_total = &total_buffer[0..truncate];
let mut start_indice = self.num_inputs.numtoa(10, &mut total_buffer);
let job_total = &total_buffer[start_indice..];


while let Some(job_id) = self.inputs.try_next(&mut input) {
if self.flags & VERBOSE_MODE != 0 {
verbose::processing_task(&stdout, job_id+1, self.num_inputs, &input);
}

let truncate = (job_id+1).numtoa(10, &mut id_buffer);
start_indice = (job_id+1).numtoa(10, &mut id_buffer);
let command = command::ParallelCommand {
slot_no: slot,
job_no: &id_buffer[0..truncate],
job_no: &id_buffer[start_indice..],
job_total: job_total,
input: &input,
command_template: self.arguments,
Expand Down
45 changes: 24 additions & 21 deletions src/execute/job_log.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use arguments::JOBLOG_8601;
use misc::NumToA;
use numtoa::NumToA;
use std::fs::File;
use std::io::{Write, BufWriter};
use time::{at, Timespec};
Expand All @@ -25,74 +25,77 @@ pub struct JobLog {
impl JobLog {
/// Writes an individual job log to the job log file, efficiently.
pub fn write_entry(&self, joblog: &mut File, id_buffer: &mut [u8], pad: usize) {
let mut start_indice;
// 1: JobID
let mut joblog = BufWriter::new(joblog);
let bytes_written = (self.job_id + 1).numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[0..bytes_written]);
for _ in 0..pad-bytes_written {
start_indice = (self.job_id + 1).numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[start_indice..]);
for _ in 0..pad-id_buffer[start_indice..].len() {
let _ = joblog.write(b" ");
}

// 2: StartTime
if self.flags & JOBLOG_8601 != 0 {
// ISO 8601 representation of the time
let tm = at(self.start_time);
// TODO: Eliminate heap allocation
let message = format!("{}-{:02}-{:02} {:02}:{:02}:{:02} ", 1900+tm.tm_year, 1+tm.tm_mon,
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
let _ = joblog.write(message.as_bytes());

} else {
// Represented in seconds, with two decimal places
let bytes_written = self.start_time.sec.numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[0..bytes_written]);
// TODO: write an abstraction for printing decimals
start_indice = self.start_time.sec.numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[start_indice..]);
let _ = joblog.write(b".");
let decimal = (self.start_time.nsec % 1_000_000_000) / 1_000_000;
if decimal == 0 {
let _ = joblog.write(b"000");
} else {
let bytes_written = decimal.numtoa(10, id_buffer);
match bytes_written {
start_indice = decimal.numtoa(10, id_buffer);
match id_buffer[start_indice..].len() {
1 => { let _ = joblog.write(b"00"); },
2 => { let _ = joblog.write(b"0"); },
_ => (),
};
let _ = joblog.write(&id_buffer[0..bytes_written]);
let _ = joblog.write(&id_buffer[start_indice..]);
}
let _ = joblog.write(b" ");
}

// 3: Runtime in seconds, with up to three decimal places.
let bytes_written = (self.runtime / 1_000_000_000).numtoa(10, id_buffer);
for _ in 0..6-bytes_written {
start_indice = (self.runtime / 1_000_000_000).numtoa(10, id_buffer);
for _ in 0..6-id_buffer[start_indice..].len() {
let _ = joblog.write(b" ");
}
let _ = joblog.write(&id_buffer[0..bytes_written]);
let _ = joblog.write(&id_buffer[start_indice..]);
let _ = joblog.write(b".");
let decimal = (self.runtime % 1_000_000_000) / 1_000_000;
if decimal == 0 {
let _ = joblog.write(b"000");
} else {
let bytes_written = decimal.numtoa(10, id_buffer);
match bytes_written {
start_indice = decimal.numtoa(10, id_buffer);
match id_buffer[start_indice..].len() {
1 => { let _ = joblog.write(b"00"); },
2 => { let _ = joblog.write(b"0"); },
_ => (),
};
let _ = joblog.write(&id_buffer[0..bytes_written]);
let _ = joblog.write(&id_buffer[start_indice..]);
}
let _ = joblog.write(b" ");

// 4: Exit Value
let bytes_written = self.exit_value.numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[0..bytes_written]);
for _ in 0..9-bytes_written {
start_indice = self.exit_value.numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[start_indice..]);
for _ in 0..9-id_buffer[start_indice..].len() {
let _ = joblog.write(b" ");
}

// 5: Signal
let bytes_written = self.signal.numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[0..bytes_written]);
for _ in 0..8-bytes_written {
start_indice = self.signal.numtoa(10, id_buffer);
let _ = joblog.write(&id_buffer[start_indice..]);
for _ in 0..8-id_buffer[start_indice..].len() {
let _ = joblog.write(b" ");
}

Expand Down
10 changes: 5 additions & 5 deletions src/filepaths.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use numtoa::NumToA;
use std::path::PathBuf;
use misc::NumToA;

#[cfg(not(windows))]
pub fn base() -> Option<PathBuf> {
Expand All @@ -19,8 +19,8 @@ pub fn new_job(base: &str, id: usize, buffer: &mut [u8]) -> (usize, String, Stri
let mut stdout = String::from(base) + "/stdout_";
let mut stderr = String::from(base) + "/stderr_";
let truncate_value = stdout.len();
let length = id.numtoa(10, buffer);
for byte in &buffer[0..length] {
let start_indice = id.numtoa(10, buffer);
for byte in &buffer[start_indice..] {
stdout.push(*byte as char);
stderr.push(*byte as char);
}
Expand All @@ -30,8 +30,8 @@ pub fn new_job(base: &str, id: usize, buffer: &mut [u8]) -> (usize, String, Stri
pub fn next_job_path(id: usize, truncate: usize, buffer: &mut [u8], stdout: &mut String, stderr: &mut String) {
stdout.truncate(truncate);
stderr.truncate(truncate);
let length = id.numtoa(10, buffer);
for byte in &buffer[0..length] {
let start_indice = id.numtoa(10, buffer);
for byte in &buffer[start_indice..] {
stdout.push(*byte as char);
stderr.push(*byte as char);
}
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
extern crate alloc_system;
extern crate arrayvec;
extern crate itoa;
extern crate numtoa;
extern crate num_cpus;
extern crate permutate;
extern crate smallvec;
Expand Down
5 changes: 0 additions & 5 deletions src/misc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
///! The purpose of this module is to supply supporting miscellanious traits for use throughout the project.
mod digits;
mod numtoa;

/// The `Digits` trait is used to get the number of digits within a number.
pub use self::digits::Digits;

/// The `NumToA` trait converts integers into their string representation,
/// but stores the results in a mutable stack-allocated byte slice.
pub use self::numtoa::NumToA;
Loading

0 comments on commit 776dbca

Please sign in to comment.