]>
git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/examples/ioat/kperf/ioat_kperf.c
4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 #define ioat_max(a,b) (((a)>(b))?(a):(b))
45 check_modules(char *driver_name
)
48 const char *proc_modules
= "/proc/modules";
51 fd
= fopen(proc_modules
, "r");
55 while (fgets(buffer
, sizeof(buffer
), fd
)) {
56 if (strstr(buffer
, driver_name
) == NULL
)
69 get_u32_from_file(const char *sysfs_file
, uint32_t *value
)
74 f
= fopen(sysfs_file
, "r");
79 if (fgets(buf
, sizeof(buf
), f
) != NULL
) {
80 *value
= strtoul(buf
, NULL
, 10);
89 get_str_from_file(const char *sysfs_file
, char *buf
, int len
)
93 f
= fopen(sysfs_file
, "r");
98 if (fgets(buf
, len
, f
) != NULL
) {
108 put_u32_to_file(const char *sysfs_file
, uint32_t value
)
114 f
= fopen(sysfs_file
, "w");
119 n
= snprintf(buf
, sizeof(buf
), "%ul", value
);
120 if ((n
< 0) || (n
>= (int)sizeof(buf
))) {
125 if (fwrite(buf
, n
, 1, f
) == 0) {
135 get_u64_from_file(const char *sysfs_file
, uint64_t *value
)
140 f
= fopen(sysfs_file
, "r");
145 if (fgets(buf
, sizeof(buf
), f
) != NULL
) {
146 *value
= strtoull(buf
, NULL
, 10);
155 get_dma_channel_count(void)
162 dir
= opendir("/sys/bus/pci/drivers/ioatdma");
167 while ((e
= readdir(dir
)) != NULL
) {
168 str
= strstr(e
->d_name
, ":");
178 usage(char *program_name
)
180 printf("%s options\n", program_name
);
181 printf("\t[-h usage]\n");
182 printf("\t[-n number of DMA channels]\n");
183 printf("\t[-q queue depth, per DMA channel]\n");
184 printf("\t[-s [n^2] transfer size, per descriptor]\n");
185 printf("\t[-t total [n^2] data to tranfer, per DMA channel]\n");
188 int main(int argc
, char *argv
[])
194 uint32_t i
, threads
= 0;
195 uint32_t ring_size
, queue_depth
= 0;
196 uint32_t transfer_size
, order
= 0;
197 uint64_t total_size
, copied
= 0;
198 uint64_t elapsed_time
= 0;
199 uint64_t total_time
= 0;
200 uint64_t perf
, total_copied
= 0;
203 if (check_modules("ioatdma")) {
204 fprintf(stderr
, "Ioat driver not loaded,"
205 " run `modprobe -v ioatdma` first\n");
208 if (check_modules("dmaperf")) {
209 fprintf(stderr
, "Kernel Ioat test driver not loaded,"
210 " run `insmod dmaperf.ko` in the kmod directory\n");
213 count
= get_dma_channel_count();
215 fprintf(stderr
, "No DMA channel found\n");
219 ring_size
= 1UL << 16;
221 while ((op
= getopt(argc
, argv
, "hn:q:s:t:")) != -1) {
224 threads
= atoi(optarg
);
225 if (threads
> count
) {
226 fprintf(stderr
, "Error: Total channel count %u\n", count
);
229 rc
= put_u32_to_file("/sys/kernel/debug/dmaperf/dmaperf/threads", threads
);
231 fprintf(stderr
, "Cannot set dma channels\n");
236 queue_depth
= atoi(optarg
);
237 if (queue_depth
> ring_size
) {
238 fprintf(stderr
, "Max Ioat DMA ring size %d\n", ring_size
);
241 rc
= put_u32_to_file("/sys/kernel/debug/dmaperf/dmaperf/queue_depth", queue_depth
);
243 fprintf(stderr
, "Cannot set queue depth\n");
248 order
= atoi(optarg
);
249 rc
= put_u32_to_file("/sys/kernel/debug/dmaperf/dmaperf/transfer_size_order", order
);
251 fprintf(stderr
, "Cannot set descriptor transfer size order\n");
256 order
= atoi(optarg
);
257 rc
= put_u32_to_file("/sys/kernel/debug/dmaperf/dmaperf/total_size_order", order
);
259 fprintf(stderr
, "Cannot set channel total transfer size order\n");
272 /* get driver configuration */
273 rc
= get_u32_from_file("/sys/kernel/debug/dmaperf/dmaperf/transfer_size_order",
276 fprintf(stderr
, "Cannot get channel descriptor transfer size\n");
279 transfer_size
= 1UL << order
;
281 rc
= get_u32_from_file("/sys/kernel/debug/dmaperf/dmaperf/total_size_order",
284 fprintf(stderr
, "Cannot get channel total transfer size\n");
287 total_size
= 1ULL << order
;
289 rc
= get_u32_from_file("/sys/kernel/debug/dmaperf/dmaperf/threads",
292 fprintf(stderr
, "Cannot get dma channel threads\n");
296 rc
= get_u32_from_file("/sys/kernel/debug/dmaperf/dmaperf/queue_depth",
299 fprintf(stderr
, "Cannot get queue depth\n");
304 "Total %d Channels, Queue_Depth %d, Transfer Size %d Bytes, Total Transfer Size %"PRIu64
" GB\n",
305 threads
, queue_depth
, transfer_size
, total_size
>> 30ULL);
307 /* run the channels */
308 rc
= put_u32_to_file("/sys/kernel/debug/dmaperf/dmaperf/run", 1);
310 fprintf(stderr
, "Cannot run the channels\n");
314 fprintf(stdout
, "Running I/O ");
316 memset(buf
, 0, BUFSIZ
);
317 /* wait all the channels to be idle */
319 fprintf(stdout
, ". ");
323 if (strstr(buf
, "idle") != NULL
) {
324 fprintf(stdout
, "\n");
329 } while (!get_str_from_file("/sys/kernel/debug/dmaperf/dmaperf/status", buf
, BUFSIZ
));
331 /* collect each channel performance data */
333 for (i
= 0; i
< threads
; i
++) {
334 /* total data transfer length for the DMA channel in Bytes */
335 snprintf(channel
, sizeof(channel
), "/sys/kernel/debug/dmaperf/dmaperf/thread_%u/copied", i
);
336 rc
= get_u64_from_file(channel
, &copied
);
338 fprintf(stderr
, "Cannot get channel copied data\n");
341 /* time in microseconds for total data transfer length */
342 snprintf(channel
, sizeof(channel
), "/sys/kernel/debug/dmaperf/dmaperf/thread_%u/elapsed_time", i
);
343 /* elapsed_time is in microsecond */
344 rc
= get_u64_from_file(channel
, &elapsed_time
);
346 fprintf(stderr
, "Cannot get channel elapsed time\n");
349 assert(elapsed_time
!= 0);
350 perf
= (copied
* 1000 * 1000) / (elapsed_time
* 1024 * 1024);
351 total_copied
+= copied
;
352 total_time
= ioat_max(elapsed_time
, total_time
);
353 fprintf(stdout
, "Channel %d Bandwidth %"PRIu64
" MiB/s\n",
357 if (total_time
&& threads
) {
358 fprintf(stdout
, "Total Channel Bandwidth: %"PRIu64
" MiB/s\n",
359 total_copied
/ total_time
);
360 fprintf(stdout
, "Average Bandwidth Per Channel: %"PRIu64
" MiB/s\n",
361 (total_copied
* 1000 * 1000) / (total_time
* threads
* 1024 * 1024));