diff --git a/V2/delay/delay_idle.txt b/V2/delay/delay_idle.txt new file mode 100644 index 0000000..d35eb49 --- /dev/null +++ b/V2/delay/delay_idle.txt @@ -0,0 +1,100 @@ + 1000000 74885 + 2000000 70188 + 3000000 100960 + 4000000 96993 + 5000000 97920 + 6000000 95671 + 7000000 95193 + 8000000 96590 + 9000000 93091 + 10000000 99800 + 11000000 97447 + 12000000 604203 + 13000000 104094 + 14000000 95803 + 15000000 95638 + 16000000 102138 + 17000000 102025 + 18000000 91546 + 19000000 96641 + 20000000 99028 + 21000000 120893 + 22000000 100362 + 23000000 96186 + 24000000 97427 + 25000000 136011 + 26000000 97303 + 27000000 106304 + 28000000 101138 + 29000000 107326 + 30000000 98307 + 31000000 102672 + 32000000 126308 + 33000000 96300 + 34000000 98373 + 35000000 95499 + 36000000 96948 + 37000000 100012 + 38000000 145522 + 39000000 103847 + 40000000 99775 + 41000000 97942 + 42000000 100953 + 43000000 145006 + 44000000 100518 + 45000000 97123 + 46000000 97738 + 47000000 163093 + 48000000 96574 + 49000000 99272 + 50000000 102283 + 51000000 141284 + 52000000 110285 + 53000000 98504 + 54000000 99068 + 55000000 105413 + 56000000 116444 + 57000000 94664 + 58000000 106010 + 59000000 96990 + 60000000 116771 + 61000000 105616 + 62000000 101075 + 63000000 108201 + 64000000 100692 + 65000000 97401 + 66000000 96037 + 67000000 156027 + 68000000 101695 + 69000000 100123 + 70000000 96780 + 71000000 97292 + 72000000 98376 + 73000000 101387 + 74000000 95961 + 75000000 98504 + 76000000 100942 + 77000000 97391 + 78000000 100610 + 79000000 95913 + 80000000 96685 + 81000000 96468 + 82000000 162291 + 83000000 138063 + 84000000 97220 + 85000000 96690 + 86000000 103070 + 87000000 96431 + 88000000 102827 + 89000000 132035 + 90000000 97650 + 91000000 101599 + 92000000 96850 + 93000000 105641 + 94000000 100006 + 95000000 96558 + 96000000 96290 + 97000000 99299 + 98000000 97207 + 99000000 96728 +100000000 99478 diff --git a/V2/delay/delay_idle_rt.txt b/V2/delay/delay_idle_rt.txt new file mode 100644 index 0000000..c1fcc6d --- /dev/null +++ b/V2/delay/delay_idle_rt.txt @@ -0,0 +1,100 @@ + 1000000 16656 + 2000000 25916 + 3000000 21532 + 4000000 21365 + 5000000 28073 + 6000000 61812 + 7000000 25969 + 8000000 22677 + 9000000 28709 + 10000000 44480 + 11000000 47542 + 12000000 44199 + 13000000 26011 + 14000000 50844 + 15000000 24220 + 16000000 47490 + 17000000 30084 + 18000000 22418 + 19000000 24543 + 20000000 130157 + 21000000 87386 + 22000000 28783 + 23000000 41480 + 24000000 34803 + 25000000 51356 + 26000000 115667 + 27000000 57116 + 28000000 25699 + 29000000 27147 + 30000000 25419 + 31000000 25408 + 32000000 25971 + 33000000 25752 + 34000000 27513 + 35000000 22138 + 36000000 25356 + 37000000 24461 + 38000000 24919 + 39000000 26107 + 40000000 27034 + 41000000 27025 + 42000000 48784 + 43000000 188304 + 44000000 65535 + 45000000 72815 + 46000000 81399 + 47000000 89305 + 48000000 72733 + 49000000 27411 + 50000000 27557 + 51000000 101504 + 52000000 26026 + 53000000 25078 + 54000000 25693 + 55000000 22349 + 56000000 26401 + 57000000 27381 + 58000000 27996 + 59000000 23610 + 60000000 28079 + 61000000 22913 + 62000000 23371 + 63000000 28777 + 64000000 26476 + 65000000 27091 + 66000000 24528 + 67000000 23684 + 68000000 23675 + 69000000 22883 + 70000000 24904 + 71000000 26925 + 72000000 22332 + 73000000 24405 + 74000000 26530 + 75000000 23811 + 76000000 26094 + 77000000 22854 + 78000000 24511 + 79000000 22833 + 80000000 31417 + 81000000 21719 + 82000000 23324 + 83000000 26803 + 84000000 26585 + 85000000 26437 + 86000000 29864 + 87000000 26000 + 88000000 28438 + 89000000 28689 + 90000000 22794 + 91000000 23148 + 92000000 22096 + 93000000 26096 + 94000000 27233 + 95000000 25661 + 96000000 24244 + 97000000 25797 + 98000000 22609 + 99000000 25673 +100000000 26861 diff --git a/V2/delay/delay_load.txt b/V2/delay/delay_load.txt new file mode 100644 index 0000000..3e35aaf --- /dev/null +++ b/V2/delay/delay_load.txt @@ -0,0 +1,100 @@ + 1000000 10251030 + 2000000 81073 + 3000000 75124 + 4000000 74646 + 5000000 63594 + 6000000 74833 + 7000000 72323 + 8000000 75230 + 9000000 75063 + 10000000 73386 + 11000000 78688 + 12000000 76335 + 13000000 74814 + 14000000 76106 + 15000000 79221 + 16000000 72074 + 17000000 77377 + 18000000 113772 + 19000000 86679 + 20000000 81460 + 21000000 78170 + 22000000 85867 + 23000000 78670 + 24000000 78711 + 25000000 73493 + 26000000 73848 + 27000000 85347 + 28000000 77889 + 29000000 83868 + 30000000 71202 + 31000000 79993 + 32000000 72849 + 33000000 84765 + 34000000 95432 + 35000000 86151 + 36000000 82703 + 37000000 85662 + 38000000 82266 + 39000000 87048 + 40000000 76569 + 41000000 137860 + 42000000 74517 + 43000000 75653 + 44000000 77154 + 45000000 80841 + 46000000 74633 + 47000000 85665 + 48000000 297163 + 49000000 78457 + 50000000 86051 + 51000000 68436 + 52000000 75406 + 53000000 387268 + 54000000 84187 + 55000000 83396 + 56000000 76563 + 57000000 82334 + 58000000 83886 + 59000000 283875 + 60000000 73294 + 61000000 76200 + 62000000 78482 + 63000000 88784 + 64000000 77055 + 65000000 79389 + 66000000 115212 + 67000000 87911 + 68000000 79776 + 69000000 83620 + 70000000 91839 + 71000000 84277 + 72000000 74006 + 73000000 78058 + 74000000 81886 + 75000000 85627 + 76000000 79419 + 77000000 87691 + 78000000 85806 + 79000000 78192 + 80000000 74693 + 81000000 79631 + 82000000 94621 + 83000000 76486 + 84000000 72257 + 85000000 78811 + 86000000 88280 + 87000000 78009 + 88000000 104926 + 89000000 78459 + 90000000 83397 + 91000000 78648 + 92000000 67649 + 93000000 79722 + 94000000 78514 + 95000000 79025 + 96000000 67974 + 97000000 78225 + 98000000 78944 + 99000000 78830 +100000000 67622 diff --git a/V2/delay/delay_load_rt.txt b/V2/delay/delay_load_rt.txt new file mode 100644 index 0000000..aee26aa --- /dev/null +++ b/V2/delay/delay_load_rt.txt @@ -0,0 +1,100 @@ + 1000000 22281 + 2000000 15345 + 3000000 14709 + 4000000 13867 + 5000000 14377 + 6000000 28221 + 7000000 37482 + 8000000 12732 + 9000000 21993 + 10000000 15681 + 11000000 27859 + 12000000 23578 + 13000000 23828 + 14000000 23871 + 15000000 22037 + 16000000 20413 + 17000000 23163 + 18000000 18153 + 19000000 23404 + 20000000 18447 + 21000000 24166 + 22000000 22385 + 23000000 28885 + 24000000 23510 + 25000000 21313 + 26000000 27656 + 27000000 18063 + 28000000 26386 + 29000000 18044 + 30000000 19023 + 31000000 19222 + 32000000 18534 + 33000000 23941 + 34000000 35909 + 35000000 18869 + 36000000 18025 + 37000000 36505 + 38000000 23891 + 39000000 19246 + 40000000 18246 + 41000000 24433 + 42000000 17966 + 43000000 27591 + 44000000 18935 + 45000000 20436 + 46000000 22770 + 47000000 19061 + 48000000 19833 + 49000000 24197 + 50000000 23719 + 51000000 19751 + 52000000 24636 + 53000000 19470 + 54000000 24147 + 55000000 27940 + 56000000 27722 + 57000000 18962 + 58000000 24368 + 59000000 19932 + 60000000 20911 + 61000000 19859 + 62000000 19745 + 63000000 24214 + 64000000 19048 + 65000000 25497 + 66000000 18716 + 67000000 27456 + 68000000 20415 + 69000000 23582 + 70000000 26332 + 71000000 20177 + 72000000 25270 + 73000000 19532 + 74000000 25042 + 75000000 24668 + 76000000 25543 + 77000000 33971 + 78000000 35887 + 79000000 46503 + 80000000 45504 + 81000000 52368 + 82000000 23348 + 83000000 36568 + 84000000 16037 + 85000000 16548 + 86000000 16017 + 87000000 37882 + 88000000 14955 + 89000000 22341 + 90000000 23477 + 91000000 14197 + 92000000 15749 + 93000000 22822 + 94000000 15521 + 95000000 45511 + 96000000 34095 + 97000000 49033 + 98000000 53501 + 99000000 36409 +100000000 37909 diff --git a/V2/delay/sleep_delay.gp b/V2/delay/sleep_delay.gp new file mode 100644 index 0000000..a5bd96f --- /dev/null +++ b/V2/delay/sleep_delay.gp @@ -0,0 +1,20 @@ +set title "{/=20 nanosleep delays}" +set terminal postscript eps enhanced +set xlabel "{/=20Period to sleep [nanoseconds]}" +set ylabel "{/=20Measured delay [nanoseconds]}" +set grid +set autoscale +set style data lines +show style data + +set output 'delay_idle.eps' +plot 'delay_idle.txt' using ($1):($2) title "{/=17 Load: no, RT: no}" lw 6 + +set output 'delay_load.eps' +plot 'delay_load.txt' using ($1):($2) title "{/=17 Load: yes, RT: no}" lw 6 + +set output 'delay_idle_rt.eps' +plot 'delay_idle_rt.txt' using ($1):($2) title "{/=17 Load: no, RT: yes}" lw 6 + +set output 'delay_load_rt.eps' +plot 'delay_load_rt.txt' using ($1):($2) title "{/=17 Load: yes, RT: yes}" lw 6 diff --git a/V2/sleep/Cargo.lock b/V2/sleep/Cargo.lock new file mode 100644 index 0000000..d352971 --- /dev/null +++ b/V2/sleep/Cargo.lock @@ -0,0 +1,62 @@ +[root] +name = "sleep" +version = "0.1.0" +dependencies = [ + "argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "argparse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_syscall" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "time" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37bb99f5e39ee8b23b6e227f5b8f024207e8616f44aa4b8c76ecd828011667ef" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" +"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" +"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/V2/sleep/Cargo.toml b/V2/sleep/Cargo.toml new file mode 100644 index 0000000..48785e9 --- /dev/null +++ b/V2/sleep/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sleep" +version = "0.1.0" +authors = ["Simon Wörner "] + +[dependencies] +argparse = ">=0.2.1" +libc = ">=0.2" +time = ">=0.1.36" diff --git a/V2/sleep/src/lib.rs b/V2/sleep/src/lib.rs new file mode 100644 index 0000000..143e7a5 --- /dev/null +++ b/V2/sleep/src/lib.rs @@ -0,0 +1,80 @@ +extern crate libc; + +use std::time::Duration; + +#[cfg(target_os = "linux")] +fn clock_nanosleep(clk_id: libc::clockid_t, + flags: libc::c_int, + rqtp: *const libc::timespec, + rmtp: *mut libc::timespec) + -> libc::c_int { + unsafe { libc::clock_nanosleep(clk_id, flags, rqtp as *const _, rmtp as *mut _) } +} + +#[cfg(target_os = "macos")] +fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int { + unsafe { libc::nanosleep(rqtp as *const _, rmtp as *mut _) } +} + +/// Sleeps for the given duration. +/// +/// Uses `clock_nanosleep` on linux and `nanosleep` on darwin. +pub fn sleep(duration: Duration) -> Result { + let ts = duration_to_timespec(duration); + let mut remain = libc::timespec { + tv_sec: 0, + tv_nsec: 0, + }; + + #[cfg(target_os = "linux")] + let ret = clock_nanosleep(libc::CLOCK_MONOTONIC, 0, &ts, &mut remain); + + #[cfg(target_os = "macos")] + let ret = nanosleep(&ts, &mut remain); + + if ret == 0 { + Ok(timespec_to_duration(remain)) + } else { + Err(ret) + } +} + +fn duration_to_timespec(duration: Duration) -> libc::timespec { + libc::timespec { + tv_sec: duration.as_secs() as libc::time_t, + tv_nsec: duration.subsec_nanos() as libc::c_long, + } +} + +fn timespec_to_duration(timespec: libc::timespec) -> Duration { + Duration::new(timespec.tv_sec as u64, timespec.tv_nsec as u32) +} + +/// Set scheduler policy and priority for process with given pid. +/// +/// If `pid` equals zero, the policy of the calling process will be set. +/// +/// # Examples +/// +/// ```rust +/// // set *round-robin* policy (default) and priority 99 (realtime) for own process +/// set_scheduler(0, libc::SCHED_RR, 99); +/// ``` +#[cfg(target_os = "linux")] +pub fn set_scheduler(pid: libc::pid_t, policy: libc::c_int, priority: libc::c_int) -> libc::c_int { + let param = libc::sched_param { sched_priority: priority }; + unsafe { libc::sched_setscheduler(pid, policy, ¶m) } +} + +/// Set scheduler *round-robin* policy (default) and priority for own process. +/// +/// # Examples +/// +/// ```rust +/// // set *round-robin* policy (default) and priority 99 (realtime) +/// set_priority(99); +/// ``` +#[cfg(target_os = "linux")] +pub fn set_priority(priority: i32) -> libc::c_int { + set_scheduler(0, libc::SCHED_RR, priority) +} diff --git a/V2/sleep/src/main.rs b/V2/sleep/src/main.rs new file mode 100644 index 0000000..7ed1183 --- /dev/null +++ b/V2/sleep/src/main.rs @@ -0,0 +1,152 @@ +#![feature(step_by)] +extern crate argparse; +extern crate sleep; +extern crate time; + +use std::io::prelude::*; +use std::fs::File; +use std::path::Path; +use std::time::Duration; + +use argparse::{ArgumentParser, Print, Store}; +use sleep::sleep; +use time::precise_time_ns; + +#[cfg(target_os = "linux")] +use argparse::StoreTrue; + +#[cfg(target_os = "linux")] +use sleep::set_priority; + +fn duration_from_ns(duration_ns: u64) -> Duration { + Duration::new(duration_ns / 1_000_000_000, + (duration_ns % 1_000_000_000) as u32) +} +fn duration_to_ns(duration: Duration) -> u64 { + duration.as_secs() * 1_000_000_000u64 + duration.subsec_nanos() as u64 +} + +fn measure_duration(sleep_duration: Duration) -> Duration { + let start = precise_time_ns(); + let _remain = sleep(sleep_duration); + let end = precise_time_ns(); + + #[cfg(debug_assertions)] + println!("remain = {:?}", _remain); + + let duration = end - start; + let duration = duration_from_ns(duration); + + #[cfg(debug_assertions)] + println!("duration = {:?}", duration); + + duration +} + +fn measure_delay(sleep_duration: Duration) -> (Duration, Duration) { + let duration = measure_duration(sleep_duration); + let delay = duration - sleep_duration; + + #[cfg(debug_assertions)] + println!("delay = {:?}", delay); + + (duration, delay) +} + +fn measure_delay_loop(sleep_duration: Duration, count: u64) -> Vec<(Duration, Duration)> { + println!("Starting measurment with period {}s {}ns for {} loops", + sleep_duration.as_secs(), + sleep_duration.subsec_nanos(), + count); + let mut data: Vec<(Duration, Duration)> = Vec::with_capacity(count as usize); + + for _ in 0..count { + let (duration, delay) = measure_delay(sleep_duration); + data.push((duration, delay)); + + #[cfg(debug_assertions)] + print_delay(duration, delay); + } + + data +} + +fn print_delay(duration: Duration, delay: Duration) { + println!("value: {} s {} ns\tdelay: {} s {} ns\trelativ delay = {:.2}%\traw_data: {:?}", + duration.as_secs(), + duration.subsec_nanos(), + delay.as_secs(), + delay.subsec_nanos(), + (duration_to_ns(delay) * 100) as f64 / duration_to_ns(duration) as f64, + delay); +} + +fn main() { + let mut min: u64 = 1_000_000; + let mut max: u64 = 100_000_000; + let mut step: u64 = 1_000_000; + let mut count: u64 = 100; + let mut output: String = "".to_string(); + let mut file: Option = None; + + #[cfg(target_os = "linux")] + let mut realtime: bool = false; + + #[cfg(target_os = "macos")] + let realtime: bool = false; + + { + let mut ap = ArgumentParser::new(); + ap.set_description(env!("CARGO_PKG_DESCRIPTION")); + ap.refer(&mut min).add_option(&["--min"], Store, "Sleep period start"); + ap.refer(&mut max).add_option(&["--max"], Store, "Sleep period end"); + ap.refer(&mut step).add_option(&["--step"], Store, "Sleep period step size"); + ap.refer(&mut count).add_option(&["--loop"], Store, "Count of measurements per period"); + #[cfg(target_os = "linux")] + ap.refer(&mut realtime).add_option(&["--rt"], StoreTrue, "Set realtime priority"); + ap.refer(&mut output).add_option(&["-o", "--out"], Store, "Output file"); + ap.add_option(&["-V", "--version"], + Print(env!("CARGO_PKG_VERSION").to_string()), + "Show version"); + ap.parse_args_or_exit(); + } + + if realtime { + #[cfg(target_os = "linux")] + let ret = set_priority(99); + + #[cfg(target_os = "macos")] + let ret = 0; + + if ret != 0 { + panic!("Set realtime priority failed."); + } + } + + if output != "" { + file = Some(File::create(Path::new(output.as_str())).expect(format!("Open file '{}' failed", + output) + .as_str())); + } + + for duration in (min..max + 1).step_by(step) { + let data = measure_delay_loop(duration_from_ns(duration), count); + let max_delay = data.iter().max().expect("Max delay not found"); + + #[cfg(debug_assertions)] + println!("max_delay = {:?}", max_delay); + + print_delay(max_delay.0, max_delay.1); + + match file.as_ref() { + Some(mut f) => { + let value = format!("{: >9} {}\n", duration, duration_to_ns(max_delay.1)); + f.write_all(value.as_bytes()).expect(format!("Write value '{}' to '{}' file failed", + value, + output) + .as_str()); + } + None => {} + } + } +} diff --git a/ci/run-cargo-test.sh b/ci/run-cargo-test.sh index bc151bb..d5d7d00 100755 --- a/ci/run-cargo-test.sh +++ b/ci/run-cargo-test.sh @@ -3,10 +3,8 @@ ERROR=0 while IFS= read -r -d '' f; do - dir="$(dirname "${f}")" - - echo "run 'cargo test' in ${dir}" - cd "${dir}" && cargo test + echo "run 'cargo test' with ${f}" + cargo test --manifest-path="${f}" if [[ $? -ne 0 ]]; then ERROR=1