benchmarks.rs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. //! Benchmarks.
  2. //!
  3. //! Note: these don't work on 16-bit machines.
  4. use criterion::{
  5. black_box, criterion_group, criterion_main, AxisScale, BenchmarkId, Criterion,
  6. PlotConfiguration,
  7. };
  8. use ibig::modular::ModuloRing;
  9. use ibig::ops::DivRem;
  10. use ibig::{ubig, UBig};
  11. use rand::prelude::*;
  12. use std::fmt::Write;
  13. fn random_ubig<R>(bits: usize, rng: &mut R) -> UBig
  14. where
  15. R: Rng + ?Sized,
  16. {
  17. rng.gen_range(ubig!(1) << (bits - 1)..ubig!(1) << bits)
  18. }
  19. fn bench_add(criterion: &mut Criterion) {
  20. let mut rng = StdRng::seed_from_u64(1);
  21. let mut group = criterion.benchmark_group("add");
  22. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  23. for log_bits in 1..=6 {
  24. let bits = 10usize.pow(log_bits);
  25. let a = random_ubig(bits, &mut rng);
  26. let b = random_ubig(bits, &mut rng);
  27. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  28. bencher.iter(|| black_box(&a) + black_box(&b))
  29. });
  30. }
  31. group.finish();
  32. }
  33. fn bench_sub(criterion: &mut Criterion) {
  34. let mut rng = StdRng::seed_from_u64(1);
  35. let mut group = criterion.benchmark_group("sub");
  36. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  37. for log_bits in 1..=6 {
  38. let bits = 10usize.pow(log_bits);
  39. let a = random_ubig(bits, &mut rng);
  40. let b = random_ubig(bits, &mut rng);
  41. let c = a + &b;
  42. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  43. bencher.iter(|| black_box(&c) - black_box(&b))
  44. });
  45. }
  46. group.finish();
  47. }
  48. fn bench_mul(criterion: &mut Criterion) {
  49. let mut rng = StdRng::seed_from_u64(1);
  50. let mut group = criterion.benchmark_group("mul");
  51. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  52. for log_bits in 1..=6 {
  53. let bits = 10usize.pow(log_bits);
  54. let a = random_ubig(bits, &mut rng);
  55. let b = random_ubig(bits, &mut rng);
  56. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  57. bencher.iter(|| black_box(&a) * black_box(&b))
  58. });
  59. }
  60. group.finish();
  61. }
  62. fn bench_div(criterion: &mut Criterion) {
  63. let mut rng = StdRng::seed_from_u64(1);
  64. let mut group = criterion.benchmark_group("div");
  65. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  66. for log_bits in 1..=6 {
  67. let bits = 10usize.pow(log_bits);
  68. let a = random_ubig(2 * bits, &mut rng);
  69. let b = random_ubig(bits, &mut rng);
  70. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  71. bencher.iter(|| black_box(&a).div_rem(black_box(&b)))
  72. });
  73. }
  74. group.finish();
  75. }
  76. fn bench_gcd(criterion: &mut Criterion) {
  77. let mut rng = StdRng::seed_from_u64(1);
  78. let mut group = criterion.benchmark_group("gcd");
  79. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  80. for log_bits in 1..=5 {
  81. let bits = 10usize.pow(log_bits);
  82. let a = random_ubig(bits, &mut rng);
  83. let b = random_ubig(bits, &mut rng);
  84. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  85. bencher.iter(|| black_box(&a).gcd(black_box(&b)))
  86. });
  87. }
  88. group.finish();
  89. let mut group = criterion.benchmark_group("extended_gcd");
  90. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  91. for log_bits in 1..=5 {
  92. let bits = 10usize.pow(log_bits);
  93. let a = random_ubig(bits, &mut rng);
  94. let b = random_ubig(bits, &mut rng);
  95. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  96. bencher.iter(|| black_box(&a).extended_gcd(black_box(&b)))
  97. });
  98. }
  99. group.finish();
  100. }
  101. fn bench_to_hex(criterion: &mut Criterion) {
  102. let mut rng = StdRng::seed_from_u64(1);
  103. let mut group = criterion.benchmark_group("to_hex");
  104. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  105. for log_bits in 1..=6 {
  106. let bits = 10usize.pow(log_bits);
  107. let a = random_ubig(bits, &mut rng);
  108. let mut out = String::with_capacity(bits / 4 + 1);
  109. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  110. bencher.iter(|| {
  111. out.clear();
  112. write!(&mut out, "{:x}", black_box(&a)).unwrap_or_else(|_| {
  113. panic!(
  114. "Called `expect()` at {}:{} (git sha: {})",
  115. file!(),
  116. line!(),
  117. option_env!("GIT_SHA").unwrap_or("unknown")
  118. )
  119. });
  120. out.len()
  121. })
  122. });
  123. }
  124. group.finish();
  125. }
  126. fn bench_to_dec(criterion: &mut Criterion) {
  127. let mut rng = StdRng::seed_from_u64(1);
  128. let mut group = criterion.benchmark_group("to_dec");
  129. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  130. for log_bits in 1..=6 {
  131. let bits = 10usize.pow(log_bits);
  132. let a = random_ubig(bits, &mut rng);
  133. let mut out = String::with_capacity(bits / 3 + 1);
  134. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  135. bencher.iter(|| {
  136. out.clear();
  137. write!(&mut out, "{}", black_box(&a)).unwrap_or_else(|_| {
  138. panic!(
  139. "Called `expect()` at {}:{} (git sha: {})",
  140. file!(),
  141. line!(),
  142. option_env!("GIT_SHA").unwrap_or("unknown")
  143. )
  144. });
  145. out.len()
  146. })
  147. });
  148. }
  149. group.finish();
  150. }
  151. fn bench_from_hex(criterion: &mut Criterion) {
  152. let mut rng = StdRng::seed_from_u64(1);
  153. let mut group = criterion.benchmark_group("from_hex");
  154. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  155. for log_bits in 1..=6 {
  156. let bits = 10usize.pow(log_bits);
  157. let a = random_ubig(bits, &mut rng);
  158. let s = a.in_radix(16).to_string();
  159. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  160. bencher.iter(|| UBig::from_str_radix(black_box(&s), 16))
  161. });
  162. }
  163. group.finish();
  164. }
  165. fn bench_from_dec(criterion: &mut Criterion) {
  166. let mut rng = StdRng::seed_from_u64(1);
  167. let mut group = criterion.benchmark_group("from_dec");
  168. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  169. for log_bits in 1..=6 {
  170. let bits = 10usize.pow(log_bits);
  171. let a = random_ubig(bits, &mut rng);
  172. let s = a.in_radix(10).to_string();
  173. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  174. bencher.iter(|| UBig::from_str_radix(black_box(&s), 10))
  175. });
  176. }
  177. group.finish();
  178. }
  179. fn bench_pow(criterion: &mut Criterion) {
  180. let mut group = criterion.benchmark_group("pow");
  181. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  182. for log_power in 1..=6 {
  183. let p = 10usize.pow(log_power);
  184. group.bench_with_input(BenchmarkId::from_parameter(p), &p, |bencher, p| {
  185. bencher.iter(|| ubig!(3).pow(*p))
  186. });
  187. }
  188. group.finish();
  189. }
  190. fn bench_modulo_mul(criterion: &mut Criterion) {
  191. let mut rng = StdRng::seed_from_u64(1);
  192. let mut group = criterion.benchmark_group("modulo_mul");
  193. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  194. for log_bits in 1..=6 {
  195. let bits = 10usize.pow(log_bits);
  196. let m = random_ubig(bits, &mut rng);
  197. let ring = ModuloRing::new(&m);
  198. let a = ring.from(random_ubig(bits, &mut rng));
  199. let b = ring.from(random_ubig(bits, &mut rng));
  200. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  201. bencher.iter(|| black_box(&a) * black_box(&b))
  202. });
  203. }
  204. group.finish();
  205. }
  206. fn bench_modulo_pow(criterion: &mut Criterion) {
  207. let mut rng = StdRng::seed_from_u64(1);
  208. let mut group = criterion.benchmark_group("modulo_pow");
  209. group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
  210. for log_bits in 1..=4 {
  211. if log_bits == 4 {
  212. group.sample_size(10);
  213. }
  214. let bits = 10usize.pow(log_bits);
  215. let m = random_ubig(bits, &mut rng);
  216. let ring = ModuloRing::new(&m);
  217. let a = ring.from(random_ubig(bits, &mut rng));
  218. let b = random_ubig(bits, &mut rng);
  219. group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
  220. bencher.iter(|| black_box(&a).pow(&b))
  221. });
  222. }
  223. group.finish();
  224. }
  225. criterion_group!(
  226. benches, bench_add, bench_sub, bench_mul, bench_div, bench_gcd, bench_to_hex, bench_to_dec,
  227. bench_from_hex, bench_from_dec, bench_pow, bench_modulo_mul, bench_modulo_pow,
  228. );
  229. criterion_main!(benches);