1
1
#[ macro_use]
2
2
extern crate alloc;
3
-
4
3
#[ macro_use]
5
4
extern crate ctor;
6
5
@@ -14,41 +13,56 @@ use alloc::alloc::Layout;
14
13
use buddy_system_allocator:: LockedHeap ;
15
14
use criterion:: { black_box, criterion_group, criterion_main, Criterion } ;
16
15
17
- // use for first three benchmark
16
+ const SMALL_SIZE : usize = 8 ;
17
+ const LARGE_SIZE : usize = 1024 * 1024 ; // 1M
18
18
const ALIGN : usize = 8 ;
19
19
20
+ /// Alloc small object
20
21
#[ inline]
21
22
pub fn small_alloc < const ORDER : usize > ( heap : & LockedHeap < ORDER > ) {
22
- const SMALL_SIZE : usize = 8 ;
23
23
let layout = unsafe { Layout :: from_size_align_unchecked ( SMALL_SIZE , ALIGN ) } ;
24
24
unsafe {
25
25
let addr = heap. alloc ( layout) ;
26
26
heap. dealloc ( addr, layout) ;
27
27
}
28
28
}
29
29
30
+ /// Alloc large object
30
31
#[ inline]
31
32
pub fn large_alloc < const ORDER : usize > ( heap : & LockedHeap < ORDER > ) {
32
- const LARGE_SIZE : usize = 1024 ;
33
33
let layout = unsafe { Layout :: from_size_align_unchecked ( LARGE_SIZE , ALIGN ) } ;
34
34
unsafe {
35
35
let addr = heap. alloc ( layout) ;
36
36
heap. dealloc ( addr, layout) ;
37
37
}
38
38
}
39
39
40
+ /// Multithreads alloc random sizes of object
40
41
#[ inline]
41
- pub fn mutil_thread_alloc < const ORDER : usize > ( heap : & ' static LockedHeap < ORDER > ) {
42
+ pub fn mutil_thread_random_size < const ORDER : usize > ( heap : & ' static LockedHeap < ORDER > ) {
42
43
const THREAD_SIZE : usize = 10 ;
44
+
45
+ use rand:: prelude:: * ;
46
+ use rand:: { Rng , SeedableRng } ;
47
+ use rand_chacha:: ChaCha8Rng ;
48
+
43
49
let mut threads = Vec :: with_capacity ( THREAD_SIZE ) ;
44
50
let alloc = Arc :: new ( heap) ;
45
51
for i in 0 ..THREAD_SIZE {
46
52
let prethread_alloc = alloc. clone ( ) ;
47
53
let handle = thread:: spawn ( move || {
48
- let layout = unsafe { Layout :: from_size_align_unchecked ( i * THREAD_SIZE , ALIGN ) } ;
49
- let addr;
50
- unsafe { addr = prethread_alloc. alloc ( layout) }
54
+ // generate a random size of object use seed `i` to ensure the fixed
55
+ // result of each turn
56
+ let mut rng = rand_chacha:: ChaCha8Rng :: seed_from_u64 ( i as u64 ) ;
57
+ // generate a random object size in range of [SMALL_SIZE ..= LARGE_SIZE]
58
+ let layout = unsafe {
59
+ Layout :: from_size_align_unchecked ( rng. gen_range ( SMALL_SIZE ..=LARGE_SIZE ) , ALIGN )
60
+ } ;
61
+ let addr = unsafe { prethread_alloc. alloc ( layout) } ;
62
+
63
+ // sleep for a while
51
64
sleep ( Duration :: from_nanos ( ( THREAD_SIZE - i) as u64 ) ) ;
65
+
52
66
unsafe { prethread_alloc. dealloc ( addr, layout) }
53
67
} ) ;
54
68
threads. push ( handle) ;
@@ -86,7 +100,7 @@ pub fn mutil_thread_alloc<const ORDER: usize>(heap: &'static LockedHeap<ORDER>)
86
100
#[ inline]
87
101
pub fn thread_test ( ) {
88
102
const N_ITERATIONS : usize = 50 ;
89
- const N_OBJECTS : usize = 3000 ;
103
+ const N_OBJECTS : usize = 30000 ;
90
104
const N_THREADS : usize = 10 ;
91
105
const OBJECT_SIZE : usize = 1 ;
92
106
@@ -102,11 +116,21 @@ pub fn thread_test() {
102
116
let handle = thread:: spawn ( move || {
103
117
// let a = new Foo * [nobjects / nthreads];
104
118
let mut a = Vec :: with_capacity ( N_OBJECTS / N_THREADS ) ;
105
- for _j in 0 ..N_ITERATIONS {
119
+ for j in 0 ..N_ITERATIONS {
106
120
// inner object:
107
121
// a[i] = new Foo[objSize];
108
- for _k in 0 ..( N_OBJECTS / N_THREADS ) {
109
- a. push ( vec ! [ Foo { a: 0 , b: 1 } ; OBJECT_SIZE ] ) ;
122
+ for k in 0 ..( N_OBJECTS / N_THREADS ) {
123
+ a. push ( vec ! [
124
+ Foo {
125
+ a: k as i32 ,
126
+ b: j as i32
127
+ } ;
128
+ OBJECT_SIZE
129
+ ] ) ;
130
+
131
+ // in order to prevent optimization delete allocation directly
132
+ // FIXME: don't know whether it works or not
133
+ a[ k] [ 0 ] . a += a[ k] [ 0 ] . b ;
110
134
}
111
135
}
112
136
// auto drop here
@@ -121,7 +145,9 @@ pub fn thread_test() {
121
145
122
146
const ORDER : usize = 32 ;
123
147
const MACHINE_ALIGN : usize = core:: mem:: size_of :: < usize > ( ) ;
124
- const KERNEL_HEAP_SIZE : usize = 16 * 1024 * 1024 ;
148
+ /// for now 128M is needed
149
+ /// TODO: reduce memory use
150
+ const KERNEL_HEAP_SIZE : usize = 128 * 1024 * 1024 ;
125
151
const HEAP_BLOCK : usize = KERNEL_HEAP_SIZE / MACHINE_ALIGN ;
126
152
static mut HEAP : [ usize ; HEAP_BLOCK ] = [ 0 ; HEAP_BLOCK ] ;
127
153
@@ -149,6 +175,7 @@ fn init_heap() {
149
175
}
150
176
}
151
177
178
+ /// Entry of benchmarks
152
179
pub fn criterion_benchmark ( c : & mut Criterion ) {
153
180
// run benchmark
154
181
c. bench_function ( "small alloc" , |b| {
@@ -157,8 +184,8 @@ pub fn criterion_benchmark(c: &mut Criterion) {
157
184
c. bench_function ( "large alloc" , |b| {
158
185
b. iter ( || large_alloc ( black_box ( & HEAP_ALLOCATOR ) ) )
159
186
} ) ;
160
- c. bench_function ( "mutil thread alloc " , |b| {
161
- b. iter ( || mutil_thread_alloc ( black_box ( & HEAP_ALLOCATOR ) ) )
187
+ c. bench_function ( "mutil thread random size " , |b| {
188
+ b. iter ( || mutil_thread_random_size ( black_box ( & HEAP_ALLOCATOR ) ) )
162
189
} ) ;
163
190
c. bench_function ( "threadtest" , |b| b. iter ( || thread_test ( ) ) ) ;
164
191
}
0 commit comments