#![allow(deprecated)]
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use multibody_dynamics::multibody::{Axis, ForwardDynamicsWorkspace, JointType, MultiBody};
use nalgebra::{Isometry3, Matrix3, SVector, Vector3, Vector6};
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};
struct CountingAlloc;
static ALLOC_CALLS: AtomicUsize = AtomicUsize::new(0);
static DEALLOC_CALLS: AtomicUsize = AtomicUsize::new(0);
static ALLOC_BYTES: AtomicUsize = AtomicUsize::new(0);
static DEALLOC_BYTES: AtomicUsize = AtomicUsize::new(0);
unsafe impl GlobalAlloc for CountingAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOC_CALLS.fetch_add(1, Ordering::Relaxed);
ALLOC_BYTES.fetch_add(layout.size(), Ordering::Relaxed);
System.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
DEALLOC_CALLS.fetch_add(1, Ordering::Relaxed);
DEALLOC_BYTES.fetch_add(layout.size(), Ordering::Relaxed);
System.dealloc(ptr, layout)
}
}
#[global_allocator]
static GLOBAL: CountingAlloc = CountingAlloc;
fn reset_alloc_counts() {
ALLOC_CALLS.store(0, Ordering::Relaxed);
DEALLOC_CALLS.store(0, Ordering::Relaxed);
ALLOC_BYTES.store(0, Ordering::Relaxed);
DEALLOC_BYTES.store(0, Ordering::Relaxed);
}
fn alloc_counts() -> (usize, usize, usize, usize) {
(
ALLOC_CALLS.load(Ordering::Relaxed),
DEALLOC_CALLS.load(Ordering::Relaxed),
ALLOC_BYTES.load(Ordering::Relaxed),
DEALLOC_BYTES.load(Ordering::Relaxed),
)
}
fn build_chain<const N: usize, const DOFS: usize>() -> MultiBody<N, DOFS> {
let mut joint_types = vec![JointType::Revolute(Axis::Z); N];
joint_types[0] = JointType::SixDOF;
let parent: Vec<u16> = (0..N as u16).collect();
let offset_mats = (0..N).map(|_| Isometry3::identity()).collect();
let masses = vec![1.0; N];
let r_cg = vec![Vector3::zeros(); N];
let inertia = Matrix3::identity();
let inertia_vec = vec![inertia; N];
MultiBody::<N, DOFS>::new(
offset_mats,
None,
None,
Some(inertia_vec),
joint_types,
parent,
Vector3::new(0.0, 0.0, 9.81),
Some(r_cg.clone()),
None,
Some(masses),
None,
None,
)
.unwrap()
}
fn bench_forward_dynamics_alloc(c: &mut Criterion) {
const N: usize = 20;
const DOFS: usize = 25; let mb = build_chain::<N, DOFS>();
let base = Isometry3::identity();
let joint_angles = SVector::<f64, { DOFS - 6 }>::from_vec(vec![0.1; DOFS - 6]);
let conf = mb.minimal_to_homogeneous_configuration(&base, &joint_angles);
let mu = SVector::<f64, DOFS>::repeat(0.01);
let thruster = vec![Vector6::zeros(); N];
let eta = SVector::<f64, DOFS>::zeros();
let zero3 = Vector3::zeros();
let rb = |_: &[Isometry3<f64>], _: &[Vector6<f64>]| nalgebra::SMatrix::<f64, 6, N>::zeros();
let mut workspace = ForwardDynamicsWorkspace::<N>::new();
let _ = mb.forward_dynamics_ab(&conf, &mu, rb, &thruster, &eta, &zero3, &zero3);
let _ = mb.forward_dynamics_ab_with_workspace(
&conf,
&mu,
rb,
&thruster,
&eta,
&zero3,
&zero3,
&mut workspace,
);
let mut group = c.benchmark_group("forward_dynamics_ab");
group.bench_function(BenchmarkId::new("allocating_api", N), |b| {
b.iter(|| {
reset_alloc_counts();
let _acc = mb.forward_dynamics_ab(&conf, &mu, rb, &thruster, &eta, &zero3, &zero3);
criterion::black_box(alloc_counts());
});
});
group.bench_function(BenchmarkId::new("workspace_api", N), |b| {
b.iter(|| {
reset_alloc_counts();
let _acc = mb.forward_dynamics_ab_with_workspace(
&conf,
&mu,
rb,
&thruster,
&eta,
&zero3,
&zero3,
&mut workspace,
);
criterion::black_box(alloc_counts());
});
});
group.finish();
reset_alloc_counts();
let _acc = mb.forward_dynamics_ab(&conf, &mu, rb, &thruster, &eta, &zero3, &zero3);
let allocating_counts = alloc_counts();
reset_alloc_counts();
let _acc = mb.forward_dynamics_ab_with_workspace(
&conf,
&mu,
rb,
&thruster,
&eta,
&zero3,
&zero3,
&mut workspace,
);
let workspace_counts = alloc_counts();
println!(
"Representative allocating API allocations: calls={} deallocs={} bytes={} dealloc_bytes={}",
allocating_counts.0, allocating_counts.1, allocating_counts.2, allocating_counts.3
);
println!(
"Representative workspace API allocations: calls={} deallocs={} bytes={} dealloc_bytes={}",
workspace_counts.0, workspace_counts.1, workspace_counts.2, workspace_counts.3
);
}
criterion_group!(benches, bench_forward_dynamics_alloc);
criterion_main!(benches);