1 /* Benchmark malloc and free functions.
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
23 #include <sys/resource.h>
24 #include "bench-timing.h"
27 /* Benchmark the malloc/free performance of a varying number of blocks of a
28 given size. This enables performance tracking of the t-cache and fastbins.
29 It tests 3 different scenarios: single-threaded using main arena,
30 multi-threaded using thread-arena, and main arena with SINGLE_THREAD_P
33 #define NUM_ITERS 200000
35 #define MAX_ALLOCS 1600
46 do_benchmark (malloc_args
*args
, int **arr
)
49 size_t iters
= args
->iters
;
50 size_t size
= args
->size
;
55 for (int j
= 0; j
< iters
; j
++)
57 for (int i
= 0; i
< n
; i
++)
58 arr
[i
] = malloc (size
);
60 for (int i
= 0; i
< n
; i
++)
66 TIMING_DIFF (args
->elapsed
, start
, stop
);
69 static malloc_args tests
[3][NUM_ALLOCS
];
70 static int allocs
[NUM_ALLOCS
] = { 25, 100, 400, MAX_ALLOCS
};
77 /* Run benchmark multi-threaded. */
78 for (int i
= 0; i
< NUM_ALLOCS
; i
++)
79 do_benchmark (&tests
[2][i
], arr
);
85 bench (unsigned long size
)
87 size_t iters
= NUM_ITERS
;
88 int **arr
= (int**) malloc (MAX_ALLOCS
* sizeof (void*));
90 for (int t
= 0; t
< 3; t
++)
91 for (int i
= 0; i
< NUM_ALLOCS
; i
++)
93 tests
[t
][i
].n
= allocs
[i
];
94 tests
[t
][i
].size
= size
;
95 tests
[t
][i
].iters
= iters
/ allocs
[i
];
97 /* Do a quick warmup run. */
99 do_benchmark (&tests
[0][i
], arr
);
102 /* Run benchmark single threaded in main_arena. */
103 for (int i
= 0; i
< NUM_ALLOCS
; i
++)
104 do_benchmark (&tests
[0][i
], arr
);
106 /* Run benchmark in a thread_arena. */
108 pthread_create (&t
, NULL
, thread_test
, (void*)arr
);
109 pthread_join (t
, NULL
);
111 /* Repeat benchmark in main_arena with SINGLE_THREAD_P == false. */
112 for (int i
= 0; i
< NUM_ALLOCS
; i
++)
113 do_benchmark (&tests
[1][i
], arr
);
119 json_init (&json_ctx
, 0, stdout
);
121 json_document_begin (&json_ctx
);
123 json_attr_string (&json_ctx
, "timing_type", TIMING_TYPE
);
125 json_attr_object_begin (&json_ctx
, "functions");
127 json_attr_object_begin (&json_ctx
, "malloc");
130 double iters2
= iters
;
132 json_attr_object_begin (&json_ctx
, "");
133 json_attr_double (&json_ctx
, "malloc_block_size", size
);
136 getrusage (RUSAGE_SELF
, &usage
);
137 json_attr_double (&json_ctx
, "max_rss", usage
.ru_maxrss
);
139 for (int i
= 0; i
< NUM_ALLOCS
; i
++)
141 sprintf (s
, "main_arena_st_allocs_%04d_time", allocs
[i
]);
142 json_attr_double (&json_ctx
, s
, tests
[0][i
].elapsed
/ iters2
);
145 for (int i
= 0; i
< NUM_ALLOCS
; i
++)
147 sprintf (s
, "main_arena_mt_allocs_%04d_time", allocs
[i
]);
148 json_attr_double (&json_ctx
, s
, tests
[1][i
].elapsed
/ iters2
);
151 for (int i
= 0; i
< NUM_ALLOCS
; i
++)
153 sprintf (s
, "thread_arena__allocs_%04d_time", allocs
[i
]);
154 json_attr_double (&json_ctx
, s
, tests
[2][i
].elapsed
/ iters2
);
157 json_attr_object_end (&json_ctx
);
159 json_attr_object_end (&json_ctx
);
161 json_attr_object_end (&json_ctx
);
163 json_document_end (&json_ctx
);
166 static void usage (const char *name
)
168 fprintf (stderr
, "%s: <alloc_size>\n", name
);
173 main (int argc
, char **argv
)
177 val
= strtol (argv
[1], NULL
, 0);
179 if (argc
> 2 || val
<= 0)