Changeset 1c49dc5 for benchmark/io


Ignore:
Timestamp:
Jul 8, 2020, 2:14:53 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
1d5e4711
Parents:
69237cd
Message:

Updated batch benchmark to factor io_uring setup

Location:
benchmark/io
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • benchmark/io/batch-readv.c

    r69237cd r1c49dc5  
    11// Program to test the optimial batchsize in a single threaded process
    22extern "C" {
    3         #ifndef _GNU_SOURCE         /* See feature_test_macros(7) */
    4         #define _GNU_SOURCE         /* See feature_test_macros(7) */
    5         #endif
    6         #include <errno.h>
    7         #include <stdio.h>
    8         #include <stdint.h>
    9         #include <stdlib.h>
    10         #include <string.h>
     3        #include <getopt.h>
    114        #include <locale.h>
    12         #include <getopt.h>
    13         #include <unistd.h>
    14         #include <sys/mman.h>
    15         #include <sys/syscall.h>
    16         #include <sys/uio.h>
    17         #include <fcntl.h>
    185        #include <time.h>                                                                               // timespec
    196        #include <sys/time.h>                                                                   // timeval
    20 
    21         #include <linux/io_uring.h>
    227}
    23 
    248
    259enum { TIMEGRAN = 1000000000LL };                                       // nanosecond granularity, except for timeval
     
    2711#include <omp.h>
    2812
    29 # ifndef __NR_io_uring_setup
    30 #  define __NR_io_uring_setup           425
    31 # endif
    32 # ifndef __NR_io_uring_enter
    33 #  define __NR_io_uring_enter           426
    34 # endif
    35 # ifndef __NR_io_uring_register
    36 #  define __NR_io_uring_register        427
    37 # endif
     13#include "io_uring.h"
    3814
    39 struct io_uring_sq {
    40         // Head and tail of the ring (associated with array)
    41         volatile uint32_t * head;
    42         volatile uint32_t * tail;
    4315
    44         // The actual kernel ring which uses head/tail
    45         // indexes into the sqes arrays
    46         uint32_t * array;
    47 
    48         // number of entries and mask to go with it
    49         const uint32_t * num;
    50         const uint32_t * mask;
    51 
    52         // Submission flags (Not sure what for)
    53         uint32_t * flags;
    54 
    55         // number of sqes not submitted (whatever that means)
    56         uint32_t * dropped;
    57 
    58         // Like head/tail but not seen by the kernel
    59         volatile uint32_t alloc;
    60 
    61         // A buffer of sqes (not the actual ring)
    62         struct io_uring_sqe * sqes;
    63 
    64         // The location and size of the mmaped area
    65         void * ring_ptr;
    66         size_t ring_sz;
    67 };
    68 
    69 struct io_uring_cq {
    70         // Head and tail of the ring
    71         volatile uint32_t * head;
    72         volatile uint32_t * tail;
    73 
    74         // number of entries and mask to go with it
    75         const uint32_t * mask;
    76         const uint32_t * num;
    77 
    78         // number of cqes not submitted (whatever that means)
    79         uint32_t * overflow;
    80 
    81         // the kernel ring
    82         struct io_uring_cqe * cqes;
    83 
    84         // The location and size of the mmaped area
    85         void * ring_ptr;
    86         size_t ring_sz;
    87 };
    88 
    89 struct io_ring {
    90         struct io_uring_sq submit_q;
    91         struct io_uring_cq completion_q;
    92         uint32_t flags;
    93         int fd;
    94 };
    95 
    96 struct fred {
    97         io_ring io;
    98 };
    99 
    100 fred self;
    10116int myfd;
    10217
     
    217132        myfd = open(__FILE__, 0);
    218133
    219         // Step 1 : call to setup
    220         struct io_uring_params params;
    221         memset(&params, 0, sizeof(params));
    222 
    223         uint32_t nentries = 2048;
    224 
    225         int fd = syscall(__NR_io_uring_setup, nentries, &params );
    226         if(fd < 0) {
    227                 fprintf(stderr, "KERNEL ERROR: IO_URING SETUP - %s\n", strerror(errno));
    228                 abort();
    229         }
    230 
    231         // Step 2 : mmap result
    232         memset(&self.io, 0, sizeof(struct io_ring));
    233         struct io_uring_sq & sq = self.io.submit_q;
    234         struct io_uring_cq & cq = self.io.completion_q;
    235 
    236         // calculate the right ring size
    237         sq.ring_sz = params.sq_off.array + (params.sq_entries * sizeof(unsigned)           );
    238         cq.ring_sz = params.cq_off.cqes  + (params.cq_entries * sizeof(struct io_uring_cqe));
    239 
    240         // Requires features
    241         // // adjust the size according to the parameters
    242         // if ((params.features & IORING_FEAT_SINGLE_MMAP) != 0) {
    243         //      cq->ring_sz = sq->ring_sz = max(cq->ring_sz, sq->ring_sz);
    244         // }
    245 
    246         // mmap the Submit Queue into existence
    247         sq.ring_ptr = mmap(0, sq.ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING);
    248         if (sq.ring_ptr == (void*)MAP_FAILED) {
    249                 fprintf(stderr, "KERNEL ERROR: IO_URING MMAP1 - %s\n", strerror(errno));
    250                 abort();
    251         }
    252 
    253         // mmap the Completion Queue into existence (may or may not be needed)
    254         // Requires features
    255         // if ((params.features & IORING_FEAT_SINGLE_MMAP) != 0) {
    256         //      cq->ring_ptr = sq->ring_ptr;
    257         // }
    258         // else {
    259                 // We need multiple call to MMAP
    260                 cq.ring_ptr = mmap(0, cq.ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_CQ_RING);
    261                 if (cq.ring_ptr == (void*)MAP_FAILED) {
    262                         munmap(sq.ring_ptr, sq.ring_sz);
    263                         fprintf(stderr, "KERNEL ERROR: IO_URING MMAP2 - %s\n", strerror(errno));
    264                         abort();
    265                 }
    266         // }
    267 
    268         // mmap the submit queue entries
    269         size_t size = params.sq_entries * sizeof(struct io_uring_sqe);
    270         sq.sqes = (struct io_uring_sqe *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQES);
    271         if (sq.sqes == (struct io_uring_sqe *)MAP_FAILED) {
    272                 munmap(sq.ring_ptr, sq.ring_sz);
    273                 if (cq.ring_ptr != sq.ring_ptr) munmap(cq.ring_ptr, cq.ring_sz);
    274                 fprintf(stderr, "KERNEL ERROR: IO_URING MMAP3 - %s\n", strerror(errno));
    275                 abort();
    276         }
    277 
    278         // Get the pointers from the kernel to fill the structure
    279         // submit queue
    280         sq.head    = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.head);
    281         sq.tail    = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.tail);
    282         sq.mask    = (   const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_mask);
    283         sq.num     = (   const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_entries);
    284         sq.flags   = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.flags);
    285         sq.dropped = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.dropped);
    286         sq.array   = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array);
    287         sq.alloc = *sq.tail;
    288 
    289         // completion queue
    290         cq.head     = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.head);
    291         cq.tail     = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.tail);
    292         cq.mask     = (   const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_mask);
    293         cq.num      = (   const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_entries);
    294         cq.overflow = (         uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.overflow);
    295         cq.cqes   = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes);
    296 
    297         self.io.fd = fd;
     134        init_uring(2048);
    298135
    299136        // Allocate the sqe
     
    344181
    345182        printf("Took %'ld ms\n", to_miliseconds(end - start));
    346         printf("Submitted       %'llu\n", submits);
    347         printf("Completed       %'llu\n", completes);
    348         printf("Submitted / sec %'.f\n", submits   / to_fseconds(end - start));
    349         printf("Completed / sec %'.f\n", completes / to_fseconds(end - start));
     183        printf("Submitted        %'llu\n", submits);
     184        printf("Completed        %'llu\n", completes);
     185        printf("Submitted / sec  %'.f\n", submits   / to_fseconds(end - start));
     186        printf("Completed / sec  %'.f\n", completes / to_fseconds(end - start));
     187        printf("ns per Submitted %'.f\n", 1000000000.0 * to_fseconds(end - start) / (submits   / batch) );
     188        printf("ns per Completed %'.f\n", 1000000000.0 * to_fseconds(end - start) / (completes / batch) );
    350189}
Note: See TracChangeset for help on using the changeset viewer.