1 #define _XOPEN_SOURCE 500
15 static struct timeval tp1,tp2;
17 static void start_timer()
19 gettimeofday(&tp1,NULL);
22 static double end_timer()
24 gettimeofday(&tp2,NULL);
25 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
26 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
32 unsigned char *buffer;
42 struct aio_block *blocks;
45 static int a_schedule(struct aio_ring *ring, int blk)
47 struct aio_block *b = &ring->blocks[blk % ring->num_blocks];
48 if (blk == b->blk) return 0;
50 if (b->buffer == NULL) {
51 b->buffer = malloc(ring->block_size);
52 if (b->buffer == NULL) goto failed;
56 b->cb = malloc(sizeof(*b->cb));
57 if (b->cb == NULL) goto failed;
60 if (b->blk != -1 && !b->done) {
61 int ret = aio_cancel(ring->fd, b->cb);
62 if (ret == AIO_NOTCANCELED) {
63 aio_suspend(&b->cb, 1, NULL);
70 memset(b->cb, 0, sizeof(*b->cb));
71 b->cb->aio_fildes = ring->fd;
72 b->cb->aio_buf = b->buffer;
73 b->cb->aio_nbytes = ring->block_size;
74 b->cb->aio_offset = blk * (off_t)ring->block_size;
75 if (aio_read(b->cb) != 0) goto failed;
89 static int a_wait(struct aio_ring *ring, int blk)
91 struct aio_block *b = &ring->blocks[blk % ring->num_blocks];
93 if (b->blk != blk) return -1;
95 if (b->done) return 0;
97 if (aio_suspend(&b->cb, 1, NULL) != 0 ||
98 aio_error(b->cb) != 0) {
108 b->nread = aio_return(b->cb);
109 if (b->nread < 0) return -1;
115 static ssize_t a_read(struct aio_ring *ring, void *buf, size_t count, off_t offset)
117 int blk_start = offset / ring->block_size;
118 int blk_end = (offset+count-1) / ring->block_size;
119 int blk_sched = blk_start + (ring->num_blocks/2);
123 if (blk_sched < blk_end) blk_sched = blk_end;
125 for (i=blk_start;i<=blk_sched;i++) {
131 int blk_offset = offset % ring->block_size;
132 int blk = offset / ring->block_size;
133 struct aio_block *b = &ring->blocks[blk % ring->num_blocks];
135 if (n > ring->block_size - blk_offset) {
136 n = ring->block_size - blk_offset;
138 if (a_wait(ring, blk) != 0) {
139 nread = pread(ring->fd, buf, n, offset);
140 printf("sync fallback\n");
142 if (n > b->nread) n = b->nread;
143 memcpy(buf, b->buffer + blk_offset, n);
147 if (total > 0) return total;
151 buf = (void *)(nread + (char *)buf);
159 static struct aio_ring *a_init(int fd, int block_size, int nblocks)
161 struct aio_ring *ring;
164 ring = malloc(sizeof(*ring));
165 if (ring == NULL) return NULL;
168 ring->num_blocks = nblocks;
169 ring->block_size = block_size;
170 ring->blocks = calloc(nblocks, sizeof(ring->blocks[0]));
171 if (ring->blocks == NULL) {
176 for (i=0;i<nblocks;i++) {
177 ring->blocks[i].blk = -1;
182 static void a_close(struct aio_ring *ring)
186 for (i=0;i<ring->num_blocks;i++) {
187 struct aio_block *b = &ring->blocks[i];
188 if (b->blk != -1 && !b->done) {
189 int ret = aio_cancel(ring->fd, b->cb);
190 if (ret == AIO_NOTCANCELED) {
191 aio_suspend(&b->cb, 1, NULL);
196 if (b->cb) free(b->cb);
197 if (b->buffer) free(b->buffer);
202 static void async_test(const char *fname, int block_size, int nblocks, int rsize)
205 struct aio_ring *ring;
212 fd = open(fname, O_RDONLY);
218 ring = a_init(fd, block_size, nblocks);
220 fprintf(stderr, "a_init faild\n");
224 while (a_read(ring, buf, sizeof(buf), offset) > 0) {
225 offset += sizeof(buf);
227 offset -= 2*sizeof(buf);
231 printf("async: %.3f MByte/sec\n", 1.0e-6 * offset / end_timer());
235 static void sync_test(const char *fname, int rsize)
244 fd = open(fname, O_RDONLY);
250 while (pread(fd, buf, sizeof(buf), offset) > 0) {
251 offset += sizeof(buf);
253 offset -= 2*sizeof(buf);
257 printf("sync : %.3f MByte/sec\n", 1.0e-6 * offset / end_timer());
261 static void usage(void)
263 printf("Usage: aiocache [options] <filename>\n");
271 int main(int argc, const char *argv[])
275 int block_size = 1024*1024;
279 while ((opt = getopt(argc, argv, "b:n:r:")) != -1) {
282 block_size = strtol(optarg, NULL, 0);
285 nblocks = strtol(optarg, NULL, 0);
288 rsize = strtol(optarg, NULL, 0);
291 printf("Invalid option '%c'\n", opt);
307 printf("Testing with block_size=%d nblocks=%d rsize=%d\n",
308 block_size,nblocks,rsize);
310 async_test(fname, block_size, nblocks, rsize);
311 sync_test(fname, rsize);
312 async_test(fname, block_size, nblocks, rsize);
313 sync_test(fname, rsize);