Browse Source

update: complete benchmark of rust ffi

master
Dnomd343 2 years ago
parent
commit
3c20cd2e2e
  1. 9
      src/klotski_core/benchmark/benchmark.h
  2. 15
      src/klotski_core/benchmark/chore.cc
  3. 194
      src/rust_ffi/src/benchmark/ffi.rs
  4. 26
      src/rust_ffi/src/benchmark/mod.rs

9
src/klotski_core/benchmark/benchmark.h

@ -8,15 +8,16 @@
/// returned according to the specified time format (seconds, milliseconds,
/// microseconds, nanoseconds).
/// The test items are all multi-thread safe(except `data_prepare`), but you
/// should not run multiple test items at the same time, which will lead to
/// unstable tests in many ways, such as changes in CPU turbo frequency.
/// The test items are all multi-thread safe, but you should not run multiple
/// test items at the same time, which will lead to unstable tests in many ways,
/// such as changes in CPU turbo frequency.
/// Pay attention to the two test items `basic_ranges` and `all_cases`, they can
/// only be run once (the reason for the construction of static data), and cannot
/// be run after other global related items.
#include <ctime>
#include <mutex>
#include <string>
#include <vector>
#include <cstdint>
@ -64,12 +65,14 @@ namespace klotski {
private:
static bool data_ready;
static std::mutex data_building;
static std::vector<RawCode> all_raw_codes;
static std::vector<ShortCode> all_short_codes;
static std::vector<CommonCode> all_common_codes;
static std::vector<std::string> all_short_codes_str;
static std::vector<std::string> all_common_codes_str;
static void build_data() noexcept;
static uint32_t random_seed() noexcept;
static double time_format(clock_t start, TIME format) noexcept;
static std::vector<uint32_t> generate_u32_rand(uint32_t count) noexcept;

15
src/klotski_core/benchmark/chore.cc

@ -8,6 +8,7 @@ using klotski::CommonCode;
using klotski::Benchmark;
bool Benchmark::data_ready = false;
std::mutex Benchmark::data_building;
std::vector<RawCode> Benchmark::all_raw_codes;
std::vector<ShortCode> Benchmark::all_short_codes;
std::vector<CommonCode> Benchmark::all_common_codes;
@ -74,10 +75,18 @@ std::vector<uint64_t> Benchmark::generate_u64_rand(uint32_t count) noexcept {
}
void Benchmark::data_preparation() noexcept {
if (Benchmark::data_ready) {
return;
if (!Benchmark::data_ready) {
if (Benchmark::data_building.try_lock()) { // mutex lock success
build_data(); // start build process
Benchmark::data_ready = true; // set available flag
} else {
Benchmark::data_building.lock(); // blocking waiting
}
Benchmark::data_building.unlock(); // release mutex
}
}
void Benchmark::build_data() noexcept {
/// short code data preparation
std::vector<uint32_t> tmp(klotski::SHORT_CODE_LIMIT);
std::iota(tmp.begin(), tmp.end(), 0);
@ -114,6 +123,4 @@ void Benchmark::data_preparation() noexcept {
for (auto &&common_code : all_common_codes) {
all_raw_codes.emplace_back(common_code.to_raw_code());
}
Benchmark::data_ready = true;
}

194
src/rust_ffi/src/benchmark/ffi.rs

@ -87,3 +87,197 @@ pub(crate) fn common_code_check_random() -> Duration {
Duration::from_ns(Core::benchmark_common_code_check_random_ns())
}
}
pub(crate) fn short_code_to_string() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_short_code_to_string_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn short_code_from_string() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_short_code_from_string_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn common_code_to_string() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_common_code_to_string_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn common_code_from_string() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_common_code_from_string_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn common_code_to_raw_code() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_common_code_to_raw_code_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn raw_code_to_common_code() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_raw_code_to_common_code_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn common_code_to_short_code() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_common_code_to_short_code_us();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_us(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn short_code_to_common_code() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_short_code_to_common_code_us();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_us(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn common_code_to_short_code_fast() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_common_code_to_short_code_fast_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn short_code_to_common_code_fast() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_short_code_to_common_code_fast_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn vertical_mirror_check() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_vertical_mirror_check_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn horizontal_mirror_check() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_horizontal_mirror_check_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn vertical_mirror_convert() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_vertical_mirror_convert_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
pub(crate) fn horizontal_mirror_convert() -> Result<Duration, &'static str> {
unsafe {
let time = Core::benchmark_horizontal_mirror_convert_ns();
match time.total_cmp(&(0 as f64)) {
Ordering::Greater => Ok(Duration::from_ns(time)),
_ => Err("data not ready"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
range_flip();
preparation();
warm_up(0x1_000_000);
assert!(basic_ranges().is_err());
assert!(all_cases().is_err());
}
#[test]
fn checker() {
preparation();
raw_code_check_random();
short_code_check_random();
common_code_check_random();
assert!(raw_code_check().is_ok());
assert!(short_code_check().is_ok());
assert!(common_code_check().is_ok());
}
#[test]
fn string() {
preparation();
assert!(short_code_to_string().is_ok());
assert!(short_code_from_string().is_ok());
assert!(common_code_to_string().is_ok());
assert!(common_code_from_string().is_ok());
}
#[test]
fn convert() {
preparation();
assert!(common_code_to_raw_code().is_ok());
assert!(raw_code_to_common_code().is_ok());
assert!(common_code_to_short_code().is_ok());
assert!(short_code_to_common_code().is_ok());
assert!(common_code_to_short_code_fast().is_ok());
assert!(short_code_to_common_code_fast().is_ok());
}
#[test]
fn mirror() {
preparation();
assert!(vertical_mirror_check().is_ok());
assert!(horizontal_mirror_check().is_ok());
assert!(vertical_mirror_convert().is_ok());
assert!(horizontal_mirror_convert().is_ok());
}
}

26
src/rust_ffi/src/benchmark/mod.rs

@ -7,12 +7,7 @@ pub fn demo() {
use ffi::*;
// println!("demo: {}", Duration::from_ps(233 as f64).to_string());
// println!("demo: {}", Duration::from_ns(233 as f64).to_string());
// println!("demo: {}", Duration::from_us(233 as f64).to_string());
// println!("demo: {}", Duration::from_ms(233 as f64).to_string());
// println!("demo: {}", Duration::from_ms(233000 as f64).to_string());
println!("start benchmark\n");
println!("warm up: {}", warm_up(0x100_0000));
println!("range flip: {}", range_flip());
@ -30,6 +25,23 @@ pub fn demo() {
println!("short code check random: {}", short_code_check_random());
println!("common code check random: {}", common_code_check_random());
println!("benchmark complete");
println!("short code to string: {}", short_code_to_string().unwrap());
println!("short code from string: {}", short_code_from_string().unwrap());
println!("common code to string: {}", common_code_to_string().unwrap());
println!("common code from string: {}", common_code_from_string().unwrap());
println!("common code to raw code: {}", common_code_to_raw_code().unwrap());
println!("raw code to common code: {}", raw_code_to_common_code().unwrap());
println!("common code to short code: {}", common_code_to_short_code().unwrap());
println!("short code to common code: {}", short_code_to_common_code().unwrap());
println!("common code to short code fast: {}", common_code_to_short_code_fast().unwrap());
println!("short code to common code fast: {}", short_code_to_common_code_fast().unwrap());
println!("vertical mirror check: {}", vertical_mirror_check().unwrap());
println!("horizontal mirror check: {}", horizontal_mirror_check().unwrap());
println!("vertical mirror convert: {}", vertical_mirror_convert().unwrap());
println!("horizontal mirror convert: {}", horizontal_mirror_convert().unwrap());
println!("\nbenchmark complete");
}

Loading…
Cancel
Save