mem.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #![feature(test)]
  2. extern crate test;
  3. use test::{black_box, Bencher};
  4. extern crate compiler_builtins;
  5. use compiler_builtins::mem::{memcmp, memcpy, memmove, memset};
  6. const WORD_SIZE: usize = core::mem::size_of::<usize>();
  7. struct AlignedVec {
  8. vec: Vec<usize>,
  9. size: usize,
  10. }
  11. impl AlignedVec {
  12. fn new(fill: u8, size: usize) -> Self {
  13. let mut broadcast = fill as usize;
  14. let mut bits = 8;
  15. while bits < WORD_SIZE * 8 {
  16. broadcast |= broadcast << bits;
  17. bits *= 2;
  18. }
  19. let vec = vec![broadcast; (size + WORD_SIZE - 1) & !WORD_SIZE];
  20. AlignedVec { vec, size }
  21. }
  22. }
  23. impl core::ops::Deref for AlignedVec {
  24. type Target = [u8];
  25. fn deref(&self) -> &[u8] {
  26. unsafe { core::slice::from_raw_parts(self.vec.as_ptr() as *const u8, self.size) }
  27. }
  28. }
  29. impl core::ops::DerefMut for AlignedVec {
  30. fn deref_mut(&mut self) -> &mut [u8] {
  31. unsafe { core::slice::from_raw_parts_mut(self.vec.as_mut_ptr() as *mut u8, self.size) }
  32. }
  33. }
  34. fn memcpy_builtin(b: &mut Bencher, n: usize, offset1: usize, offset2: usize) {
  35. let v1 = AlignedVec::new(1, n + offset1);
  36. let mut v2 = AlignedVec::new(0, n + offset2);
  37. b.bytes = n as u64;
  38. b.iter(|| {
  39. let src: &[u8] = black_box(&v1[offset1..]);
  40. let dst: &mut [u8] = black_box(&mut v2[offset2..]);
  41. dst.copy_from_slice(src);
  42. })
  43. }
  44. fn memcpy_rust(b: &mut Bencher, n: usize, offset1: usize, offset2: usize) {
  45. let v1 = AlignedVec::new(1, n + offset1);
  46. let mut v2 = AlignedVec::new(0, n + offset2);
  47. b.bytes = n as u64;
  48. b.iter(|| {
  49. let src: &[u8] = black_box(&v1[offset1..]);
  50. let dst: &mut [u8] = black_box(&mut v2[offset2..]);
  51. unsafe { memcpy(dst.as_mut_ptr(), src.as_ptr(), n) }
  52. })
  53. }
  54. fn memset_builtin(b: &mut Bencher, n: usize, offset: usize) {
  55. let mut v1 = AlignedVec::new(0, n + offset);
  56. b.bytes = n as u64;
  57. b.iter(|| {
  58. let dst: &mut [u8] = black_box(&mut v1[offset..]);
  59. let val: u8 = black_box(27);
  60. for b in dst {
  61. *b = val;
  62. }
  63. })
  64. }
  65. fn memset_rust(b: &mut Bencher, n: usize, offset: usize) {
  66. let mut v1 = AlignedVec::new(0, n + offset);
  67. b.bytes = n as u64;
  68. b.iter(|| {
  69. let dst: &mut [u8] = black_box(&mut v1[offset..]);
  70. let val = black_box(27);
  71. unsafe { memset(dst.as_mut_ptr(), val, n) }
  72. })
  73. }
  74. fn memcmp_builtin(b: &mut Bencher, n: usize) {
  75. let v1 = AlignedVec::new(0, n);
  76. let mut v2 = AlignedVec::new(0, n);
  77. v2[n - 1] = 1;
  78. b.bytes = n as u64;
  79. b.iter(|| {
  80. let s1: &[u8] = black_box(&v1);
  81. let s2: &[u8] = black_box(&v2);
  82. s1.cmp(s2)
  83. })
  84. }
  85. fn memcmp_rust(b: &mut Bencher, n: usize) {
  86. let v1 = AlignedVec::new(0, n);
  87. let mut v2 = AlignedVec::new(0, n);
  88. v2[n - 1] = 1;
  89. b.bytes = n as u64;
  90. b.iter(|| {
  91. let s1: &[u8] = black_box(&v1);
  92. let s2: &[u8] = black_box(&v2);
  93. unsafe { memcmp(s1.as_ptr(), s2.as_ptr(), n) }
  94. })
  95. }
  96. fn memmove_builtin(b: &mut Bencher, n: usize, offset: usize) {
  97. let mut v = AlignedVec::new(0, n + n / 2 + offset);
  98. b.bytes = n as u64;
  99. b.iter(|| {
  100. let s: &mut [u8] = black_box(&mut v);
  101. s.copy_within(0..n, n / 2 + offset);
  102. })
  103. }
  104. fn memmove_rust(b: &mut Bencher, n: usize, offset: usize) {
  105. let mut v = AlignedVec::new(0, n + n / 2 + offset);
  106. b.bytes = n as u64;
  107. b.iter(|| {
  108. let dst: *mut u8 = black_box(&mut v[n / 2 + offset..]).as_mut_ptr();
  109. let src: *const u8 = black_box(&v).as_ptr();
  110. unsafe { memmove(dst, src, n) };
  111. })
  112. }
  113. #[bench]
  114. fn memcpy_builtin_4096(b: &mut Bencher) {
  115. memcpy_builtin(b, 4096, 0, 0)
  116. }
  117. #[bench]
  118. fn memcpy_rust_4096(b: &mut Bencher) {
  119. memcpy_rust(b, 4096, 0, 0)
  120. }
  121. #[bench]
  122. fn memcpy_builtin_1048576(b: &mut Bencher) {
  123. memcpy_builtin(b, 1048576, 0, 0)
  124. }
  125. #[bench]
  126. fn memcpy_rust_1048576(b: &mut Bencher) {
  127. memcpy_rust(b, 1048576, 0, 0)
  128. }
  129. #[bench]
  130. fn memcpy_builtin_4096_offset(b: &mut Bencher) {
  131. memcpy_builtin(b, 4096, 65, 65)
  132. }
  133. #[bench]
  134. fn memcpy_rust_4096_offset(b: &mut Bencher) {
  135. memcpy_rust(b, 4096, 65, 65)
  136. }
  137. #[bench]
  138. fn memcpy_builtin_1048576_offset(b: &mut Bencher) {
  139. memcpy_builtin(b, 1048576, 65, 65)
  140. }
  141. #[bench]
  142. fn memcpy_rust_1048576_offset(b: &mut Bencher) {
  143. memcpy_rust(b, 1048576, 65, 65)
  144. }
  145. #[bench]
  146. fn memcpy_builtin_4096_misalign(b: &mut Bencher) {
  147. memcpy_builtin(b, 4096, 65, 66)
  148. }
  149. #[bench]
  150. fn memcpy_rust_4096_misalign(b: &mut Bencher) {
  151. memcpy_rust(b, 4096, 65, 66)
  152. }
  153. #[bench]
  154. fn memcpy_builtin_1048576_misalign(b: &mut Bencher) {
  155. memcpy_builtin(b, 1048576, 65, 66)
  156. }
  157. #[bench]
  158. fn memcpy_rust_1048576_misalign(b: &mut Bencher) {
  159. memcpy_rust(b, 1048576, 65, 66)
  160. }
  161. #[bench]
  162. fn memset_builtin_4096(b: &mut Bencher) {
  163. memset_builtin(b, 4096, 0)
  164. }
  165. #[bench]
  166. fn memset_rust_4096(b: &mut Bencher) {
  167. memset_rust(b, 4096, 0)
  168. }
  169. #[bench]
  170. fn memset_builtin_1048576(b: &mut Bencher) {
  171. memset_builtin(b, 1048576, 0)
  172. }
  173. #[bench]
  174. fn memset_rust_1048576(b: &mut Bencher) {
  175. memset_rust(b, 1048576, 0)
  176. }
  177. #[bench]
  178. fn memset_builtin_4096_offset(b: &mut Bencher) {
  179. memset_builtin(b, 4096, 65)
  180. }
  181. #[bench]
  182. fn memset_rust_4096_offset(b: &mut Bencher) {
  183. memset_rust(b, 4096, 65)
  184. }
  185. #[bench]
  186. fn memset_builtin_1048576_offset(b: &mut Bencher) {
  187. memset_builtin(b, 1048576, 65)
  188. }
  189. #[bench]
  190. fn memset_rust_1048576_offset(b: &mut Bencher) {
  191. memset_rust(b, 1048576, 65)
  192. }
  193. #[bench]
  194. fn memcmp_builtin_4096(b: &mut Bencher) {
  195. memcmp_builtin(b, 4096)
  196. }
  197. #[bench]
  198. fn memcmp_rust_4096(b: &mut Bencher) {
  199. memcmp_rust(b, 4096)
  200. }
  201. #[bench]
  202. fn memcmp_builtin_1048576(b: &mut Bencher) {
  203. memcmp_builtin(b, 1048576)
  204. }
  205. #[bench]
  206. fn memcmp_rust_1048576(b: &mut Bencher) {
  207. memcmp_rust(b, 1048576)
  208. }
  209. #[bench]
  210. fn memmove_builtin_4096(b: &mut Bencher) {
  211. memmove_builtin(b, 4096, 0)
  212. }
  213. #[bench]
  214. fn memmove_rust_4096(b: &mut Bencher) {
  215. memmove_rust(b, 4096, 0)
  216. }
  217. #[bench]
  218. fn memmove_builtin_1048576(b: &mut Bencher) {
  219. memmove_builtin(b, 1048576, 0)
  220. }
  221. #[bench]
  222. fn memmove_rust_1048576(b: &mut Bencher) {
  223. memmove_rust(b, 1048576, 0)
  224. }
  225. #[bench]
  226. fn memmove_builtin_4096_misalign(b: &mut Bencher) {
  227. memmove_builtin(b, 4096, 1)
  228. }
  229. #[bench]
  230. fn memmove_rust_4096_misalign(b: &mut Bencher) {
  231. memmove_rust(b, 4096, 1)
  232. }
  233. #[bench]
  234. fn memmove_builtin_1048576_misalign(b: &mut Bencher) {
  235. memmove_builtin(b, 1048576, 1)
  236. }
  237. #[bench]
  238. fn memmove_rust_1048576_misalign(b: &mut Bencher) {
  239. memmove_rust(b, 1048576, 1)
  240. }