]>
Commit | Line | Data |
---|---|---|
d01cbb6e | 1 | /* Measure memcpy performance. |
dff8da6b | 2 | Copyright (C) 2016-2024 Free Software Foundation, Inc. |
d01cbb6e SP |
3 | This file is part of the GNU C Library. |
4 | ||
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. | |
9 | ||
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. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
d01cbb6e | 18 | |
f392915d WD |
19 | #define MIN_SIZE 32768 |
20 | #define MAX_SIZE (1024*1024) | |
21 | #define NUM_TESTS 16384 | |
22 | ||
23 | #define MIN_PAGE_SIZE (MAX_SIZE + getpagesize()) | |
d01cbb6e | 24 | #define TEST_MAIN |
29d92a8e | 25 | #define TEST_NAME "memcpy" |
d01cbb6e SP |
26 | #include "bench-string.h" |
27 | #include <assert.h> | |
5ee1e3ce | 28 | #include "json-lib.h" |
d01cbb6e | 29 | |
511c91b1 | 30 | IMPL (memcpy, 1) |
d01cbb6e SP |
31 | |
32 | typedef struct { uint16_t size; uint16_t freq; } freq_data_t; | |
511c91b1 | 33 | typedef struct { uint8_t align; uint16_t freq; } align_data_t; |
d01cbb6e | 34 | |
511c91b1 | 35 | #define SIZE_NUM 65536 |
d01cbb6e SP |
36 | #define SIZE_MASK (SIZE_NUM-1) |
37 | static uint8_t size_arr[SIZE_NUM]; | |
38 | ||
511c91b1 | 39 | /* Frequency data for memcpy of less than 4096 bytes based on SPEC2017. */ |
d01cbb6e SP |
40 | static freq_data_t size_freq[] = |
41 | { | |
f392915d WD |
42 | {32,22320}, { 16,9554}, { 8,8915}, {152,5327}, { 4,2159}, {292,2035}, |
43 | { 12,1608}, { 24,1343}, {1152,895}, {144, 813}, {884, 733}, {284, 721}, | |
511c91b1 | 44 | {120, 661}, { 2, 649}, {882, 550}, { 5, 475}, { 7, 461}, {108, 460}, |
f392915d | 45 | { 10, 361}, { 9, 361}, { 6, 334}, { 3, 326}, {464, 308}, {2048,303}, |
511c91b1 | 46 | { 1, 298}, { 64, 250}, { 11, 197}, {296, 194}, { 68, 187}, { 15, 185}, |
f392915d WD |
47 | {192, 184}, {1764,183}, { 13, 173}, {560, 126}, {160, 115}, {288, 96}, |
48 | {104, 96}, {1144, 83}, { 18, 80}, { 23, 78}, { 40, 77}, { 19, 68}, | |
49 | { 48, 63}, { 17, 57}, { 72, 54}, {1280, 51}, { 20, 49}, { 28, 47}, | |
511c91b1 | 50 | { 22, 46}, {640, 45}, { 25, 41}, { 14, 40}, { 56, 37}, { 27, 35}, |
f392915d | 51 | { 35, 33}, {384, 33}, { 29, 32}, { 80, 30}, {4095, 22}, {232, 22}, |
511c91b1 | 52 | { 36, 19}, {184, 17}, { 21, 17}, {256, 16}, { 44, 15}, { 26, 15}, |
f392915d | 53 | { 31, 14}, { 88, 14}, {176, 13}, { 33, 12}, {1024, 12}, {208, 11}, |
511c91b1 | 54 | { 62, 11}, {128, 10}, {704, 10}, {324, 10}, { 96, 10}, { 60, 9}, |
f392915d | 55 | {136, 9}, {124, 9}, { 34, 8}, { 30, 8}, {480, 8}, {1344, 8}, |
511c91b1 WD |
56 | {273, 7}, {520, 7}, {112, 6}, { 52, 6}, {344, 6}, {336, 6}, |
57 | {504, 5}, {168, 5}, {424, 5}, { 0, 4}, { 76, 3}, {200, 3}, | |
58 | {512, 3}, {312, 3}, {240, 3}, {960, 3}, {264, 2}, {672, 2}, | |
59 | { 38, 2}, {328, 2}, { 84, 2}, { 39, 2}, {216, 2}, { 42, 2}, | |
f392915d WD |
60 | { 37, 2}, {1608, 2}, { 70, 2}, { 46, 2}, {536, 2}, {280, 1}, |
61 | {248, 1}, { 47, 1}, {1088, 1}, {1288, 1}, {224, 1}, { 41, 1}, | |
511c91b1 WD |
62 | { 50, 1}, { 49, 1}, {808, 1}, {360, 1}, {440, 1}, { 43, 1}, |
63 | { 45, 1}, { 78, 1}, {968, 1}, {392, 1}, { 54, 1}, { 53, 1}, | |
64 | { 59, 1}, {376, 1}, {664, 1}, { 58, 1}, {272, 1}, { 66, 1}, | |
f392915d | 65 | {2688, 1}, {472, 1}, {568, 1}, {720, 1}, { 51, 1}, { 63, 1}, |
511c91b1 WD |
66 | { 86, 1}, {496, 1}, {776, 1}, { 57, 1}, {680, 1}, {792, 1}, |
67 | {122, 1}, {760, 1}, {824, 1}, {552, 1}, { 67, 1}, {456, 1}, | |
68 | {984, 1}, { 74, 1}, {408, 1}, { 75, 1}, { 92, 1}, {576, 1}, | |
69 | {116, 1}, { 65, 1}, {117, 1}, { 82, 1}, {352, 1}, { 55, 1}, | |
70 | {100, 1}, { 90, 1}, {696, 1}, {111, 1}, {880, 1}, { 79, 1}, | |
f392915d | 71 | {488, 1}, { 61, 1}, {114, 1}, { 94, 1}, {1032, 1}, { 98, 1}, |
511c91b1 | 72 | { 87, 1}, {584, 1}, { 85, 1}, {648, 1}, {0, 0} |
d01cbb6e SP |
73 | }; |
74 | ||
511c91b1 | 75 | #define ALIGN_NUM 1024 |
d01cbb6e SP |
76 | #define ALIGN_MASK (ALIGN_NUM-1) |
77 | static uint8_t src_align_arr[ALIGN_NUM]; | |
78 | static uint8_t dst_align_arr[ALIGN_NUM]; | |
79 | ||
511c91b1 | 80 | /* Source alignment frequency for memcpy based on SPEC2017. */ |
d01cbb6e SP |
81 | static align_data_t src_align_freq[] = |
82 | { | |
511c91b1 | 83 | {8, 300}, {16, 292}, {32, 168}, {64, 153}, {4, 79}, {2, 14}, {1, 18}, {0, 0} |
d01cbb6e SP |
84 | }; |
85 | ||
511c91b1 | 86 | /* Destination alignment frequency for memcpy based on SPEC2017. */ |
d01cbb6e SP |
87 | static align_data_t dst_align_freq[] = |
88 | { | |
511c91b1 | 89 | {8, 265}, {16, 263}, {64, 209}, {32, 174}, {4, 90}, {2, 10}, {1, 13}, {0, 0} |
d01cbb6e SP |
90 | }; |
91 | ||
92 | typedef struct | |
93 | { | |
511c91b1 WD |
94 | uint64_t src : 24; |
95 | uint64_t dst : 24; | |
96 | uint64_t len : 16; | |
d01cbb6e SP |
97 | } copy_t; |
98 | ||
f392915d | 99 | static copy_t test_arr[NUM_TESTS]; |
d01cbb6e SP |
100 | |
101 | typedef char *(*proto_t) (char *, const char *, size_t); | |
102 | ||
103 | static void | |
104 | init_copy_distribution (void) | |
105 | { | |
106 | int i, j, freq, size, n; | |
107 | ||
108 | for (n = i = 0; (freq = size_freq[i].freq) != 0; i++) | |
109 | for (j = 0, size = size_freq[i].size; j < freq; j++) | |
110 | size_arr[n++] = size; | |
111 | assert (n == SIZE_NUM); | |
112 | ||
113 | for (n = i = 0; (freq = src_align_freq[i].freq) != 0; i++) | |
114 | for (j = 0, size = src_align_freq[i].align; j < freq; j++) | |
115 | src_align_arr[n++] = size - 1; | |
116 | assert (n == ALIGN_NUM); | |
117 | ||
118 | for (n = i = 0; (freq = dst_align_freq[i].freq) != 0; i++) | |
119 | for (j = 0, size = dst_align_freq[i].align; j < freq; j++) | |
120 | dst_align_arr[n++] = size - 1; | |
121 | assert (n == ALIGN_NUM); | |
122 | } | |
123 | ||
124 | ||
125 | static void | |
5ee1e3ce SP |
126 | do_one_test (json_ctx_t *json_ctx, impl_t *impl, char *dst, char *src, |
127 | copy_t *copy, size_t n) | |
d01cbb6e SP |
128 | { |
129 | timing_t start, stop, cur; | |
26234791 | 130 | size_t iters = INNER_LOOP_ITERS_MEDIUM / 2; |
d01cbb6e | 131 | |
511c91b1 WD |
132 | for (int j = 0; j < n; j++) |
133 | CALL (impl, dst + copy[j].dst, src + copy[j].src, copy[j].len); | |
134 | ||
d01cbb6e SP |
135 | TIMING_NOW (start); |
136 | for (int i = 0; i < iters; ++i) | |
137 | for (int j = 0; j < n; j++) | |
138 | CALL (impl, dst + copy[j].dst, src + copy[j].src, copy[j].len); | |
139 | TIMING_NOW (stop); | |
140 | ||
141 | TIMING_DIFF (cur, start, stop); | |
142 | ||
5ee1e3ce | 143 | json_element_double (json_ctx, (double) cur / (double) iters); |
d01cbb6e SP |
144 | } |
145 | ||
146 | static void | |
5ee1e3ce | 147 | do_test (json_ctx_t *json_ctx, size_t max_size) |
d01cbb6e | 148 | { |
511c91b1 WD |
149 | int i; |
150 | ||
151 | memset (buf1, 1, max_size); | |
d01cbb6e SP |
152 | |
153 | /* Create a random set of copies with the given size and alignment | |
154 | distributions. */ | |
f392915d | 155 | for (i = 0; i < NUM_TESTS; i++) |
d01cbb6e | 156 | { |
f392915d WD |
157 | test_arr[i].dst = (rand () & (max_size - 1)); |
158 | test_arr[i].dst &= ~dst_align_arr[rand () & ALIGN_MASK]; | |
159 | test_arr[i].src = (rand () & (max_size - 1)); | |
160 | test_arr[i].src &= ~src_align_arr[rand () & ALIGN_MASK]; | |
161 | test_arr[i].len = size_arr[rand () & SIZE_MASK]; | |
d01cbb6e SP |
162 | } |
163 | ||
5ee1e3ce | 164 | json_element_object_begin (json_ctx); |
f12ec02f | 165 | json_attr_uint (json_ctx, "length", (double) max_size); |
5ee1e3ce | 166 | json_array_begin (json_ctx, "timings"); |
d01cbb6e SP |
167 | |
168 | FOR_EACH_IMPL (impl, 0) | |
f392915d | 169 | do_one_test (json_ctx, impl, (char *) buf2, (char *) buf1, test_arr, i); |
d01cbb6e | 170 | |
5ee1e3ce SP |
171 | json_array_end (json_ctx); |
172 | json_element_object_end (json_ctx); | |
d01cbb6e SP |
173 | } |
174 | ||
175 | int | |
176 | test_main (void) | |
177 | { | |
5ee1e3ce SP |
178 | json_ctx_t json_ctx; |
179 | ||
d01cbb6e SP |
180 | test_init (); |
181 | init_copy_distribution (); | |
182 | ||
5ee1e3ce SP |
183 | json_init (&json_ctx, 0, stdout); |
184 | ||
185 | json_document_begin (&json_ctx); | |
186 | json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); | |
187 | ||
188 | json_attr_object_begin (&json_ctx, "functions"); | |
7ee38e60 | 189 | json_attr_object_begin (&json_ctx, TEST_NAME); |
5ee1e3ce SP |
190 | json_attr_string (&json_ctx, "bench-variant", "random"); |
191 | ||
192 | json_array_begin (&json_ctx, "ifuncs"); | |
d01cbb6e | 193 | FOR_EACH_IMPL (impl, 0) |
5ee1e3ce SP |
194 | json_element_string (&json_ctx, impl->name); |
195 | json_array_end (&json_ctx); | |
d01cbb6e | 196 | |
5ee1e3ce | 197 | json_array_begin (&json_ctx, "results"); |
f392915d WD |
198 | for (int i = MIN_SIZE; i <= MAX_SIZE; i = i * 2) |
199 | do_test (&json_ctx, i); | |
5ee1e3ce SP |
200 | |
201 | json_array_end (&json_ctx); | |
202 | json_attr_object_end (&json_ctx); | |
203 | json_attr_object_end (&json_ctx); | |
204 | json_document_end (&json_ctx); | |
d01cbb6e SP |
205 | |
206 | return ret; | |
207 | } | |
208 | ||
209 | #include <support/test-driver.c> |