1 #define _XOPEN_SOURCE 500
16 static struct timeval tp1,tp2;
18 static void start_timer()
20 gettimeofday(&tp1,NULL);
23 static double end_timer()
25 gettimeofday(&tp2,NULL);
26 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
27 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
33 unsigned char *buffer;
43 struct io_block *blocks;
47 static int a_schedule(struct io_ring *ring, int blk)
49 struct io_block *b = &ring->blocks[blk % ring->num_blocks];
51 if (blk == b->blk) return 0;
53 if (b->buffer == NULL) {
54 b->buffer = malloc(ring->block_size);
55 if (b->buffer == NULL) goto failed;
59 b->cb = malloc(sizeof(*b->cb));
60 if (b->cb == NULL) goto failed;
63 if (b->blk != -1 && !b->done) {
65 int ret = io_cancel(ring->io_ctx, b->cb, &res);
73 memset(b->cb, 0, sizeof(*b->cb));
74 io_prep_pread(b->cb, ring->fd, b->buffer, ring->block_size,
75 blk * (off_t)ring->block_size);
76 if (io_submit(ring->io_ctx, 1, &b->cb) != 0) goto failed;
89 static int a_wait(struct io_ring *ring, int blk)
91 struct io_block *b = &ring->blocks[blk % ring->num_blocks];
92 struct io_event ev[10];
94 if (b->blk != blk) return -1;
97 int i, nr = io_getevents(ring->io_ctx, 1, 10, ev, NULL);
99 struct iocb *cb = ev[i].obj;
100 struct io_block *b2 = &ring->blocks[cb->key % ring->num_blocks];
102 b2->nread = ev[i].res;
106 if (b->nread < 0) return -1;
112 static ssize_t a_read(struct io_ring *ring, void *buf, size_t count, off_t offset)
114 int blk_start = offset / ring->block_size;
115 int blk_end = (offset+count-1) / ring->block_size;
116 int blk_sched = blk_start + (ring->num_blocks/2);
120 if (blk_sched < blk_end) blk_sched = blk_end;
122 for (i=blk_start;i<=blk_sched;i++) {
128 int blk_offset = offset % ring->block_size;
129 int blk = offset / ring->block_size;
130 struct io_block *b = &ring->blocks[blk % ring->num_blocks];
132 if (n > ring->block_size - blk_offset) {
133 n = ring->block_size - blk_offset;
135 if (a_wait(ring, blk) != 0) {
136 nread = pread(ring->fd, buf, n, offset);
137 printf("sync fallback\n");
139 if (n > b->nread) n = b->nread;
140 memcpy(buf, b->buffer + blk_offset, n);
144 if (total > 0) return total;
148 buf = (void *)(nread + (char *)buf);
156 static struct io_ring *a_init(int fd, int block_size, int nblocks)
158 struct io_ring *ring;
162 ring = malloc(sizeof(*ring));
163 if (ring == NULL) return NULL;
165 memset(ring, 0, sizeof(*ring));
166 ret = io_queue_init(nblocks, &ring->io_ctx);
172 ring->num_blocks = nblocks;
173 ring->block_size = block_size;
174 ring->blocks = calloc(nblocks, sizeof(ring->blocks[0]));
175 if (ring->blocks == NULL) {
180 for (i=0;i<nblocks;i++) {
181 ring->blocks[i].blk = -1;
186 static void a_close(struct io_ring *ring)
190 for (i=0;i<ring->num_blocks;i++) {
191 struct io_block *b = &ring->blocks[i];
192 if (b->blk != -1 && !b->done) {
194 int ret = io_cancel(ring->io_ctx, b->cb, &res);
196 a_wait(ring, b->blk);
199 if (b->cb) free(b->cb);
200 if (b->buffer) free(b->buffer);
205 static void async_test(const char *fname, int block_size, int nblocks, int rsize)
208 struct io_ring *ring;
215 fd = open(fname, O_RDONLY);
221 ring = a_init(fd, block_size, nblocks);
223 fprintf(stderr, "a_init faild\n");
227 while (a_read(ring, buf, sizeof(buf), offset) > 0) {
228 offset += sizeof(buf);
230 offset -= 2*sizeof(buf);
234 printf("async: %.3f MByte/sec\n", 1.0e-6 * offset / end_timer());
238 static void sync_test(const char *fname, int rsize)
247 fd = open(fname, O_RDONLY);
253 while (pread(fd, buf, sizeof(buf), offset) > 0) {
254 offset += sizeof(buf);
256 offset -= 2*sizeof(buf);
260 printf("sync : %.3f MByte/sec\n", 1.0e-6 * offset / end_timer());
264 static void usage(void)
266 printf("Usage: aiocache [options] <filename>\n");
274 int main(int argc, const char *argv[])
278 int block_size = 1024*1024;
282 while ((opt = getopt(argc, argv, "b:n:r:")) != -1) {
285 block_size = strtol(optarg, NULL, 0);
288 nblocks = strtol(optarg, NULL, 0);
291 rsize = strtol(optarg, NULL, 0);
294 printf("Invalid option '%c'\n", opt);
310 printf("Testing with block_size=%d nblocks=%d rsize=%d\n",
311 block_size,nblocks,rsize);
313 async_test(fname, block_size, nblocks, rsize);
314 sync_test(fname, rsize);
315 async_test(fname, block_size, nblocks, rsize);
316 sync_test(fname, rsize);