Messages in this thread Patch in this message |  | | Date | Tue, 9 Apr 1996 01:01:33 +0000 (GMT) | From | Gerard Roudier <> | Subject | Re: File read-ahead and Linux-1.3.85 |
| |
Matti,
On Mon, 8 Apr 1996, Matti E Aarnio wrote:
> > Linux-1.3.85 also does > .... > > - file read-ahead code update > > This should have speeded up the system, right ? > (Such claim was made by the author of that patch..)
I am sure that you did not try my previous patch. My patch was experimental but worked fine. Linux patch for asynchronous read-ahead is quite aesthetic but quite bad.
> > -------Sequential Output-------- ---Sequential Input-- --Random-- > -Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks--- > Machine MB K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU /sec %CPU > Lnx1380 100 3221 60.4 2973 19.9 1150 13.9 2300 44.1 2844 12.9 45.9 2.3 > Lnx1384 180 2395 43.4 2714 17.2 1339 16.7 2519 47.2 3253 14.6 69.2 2.9 > Lnx1385 180 2520 44.9 3204 19.8 1258 16.1 2721 56.6 3220 16.0 70.1 3.0 > > This machine is a 266 MHz Alpha-XL with integrated NCR 53C810, and > Seagate ST31230N SCSI-disk. At the last two tests the system had > 128 MB memory, while with the first one there was propably 32 MB memory. > > My point, either we are limited by the disk, or perhaps the NCR-driver > is not as good as it could be... The read-ahead does not help noticeably. > ... > > Now, go test it out to see if I broke something else while the above got > > fixed.. > > Linus > > /Matti Aarnio <mea@utu.fi> >
I have done some tests with 1.3.85 and 1.3.84 patched. P90/24MB/IBMS12/NCR53C810/BSD driver (I skipped seekers)
Here are the results of those tests with Bonnie: ------------------------------------------------
Messages "XXXXXX ...." are some statistics printed by the driver about xfer sizes.
Here is the output I get with 1.3.85 unpatched: ----------------------------------------------- Writing with putc()... XXXXXXXXXX - Xfer length min=1024 max=124928 average=96327 done Rewriting... XXXXXXXXXX - Xfer length min=1024 max=124928 average=14494 done Writing intelligently... XXXXXXXXXX - Xfer length min=1024 max=124928 average=111884 done Reading with getc()... XXXXXXXXXX - Xfer length min=1024 max=24576 average=4164 done Reading intelligently... XXXXXXXXXX - Xfer length min=1024 max=16384 average=7973 done
Here is the output I get with 1.3.84 patched for asynchronous read-ahead: -------------------------------------------------------------------------
Writing with putc()... XXXXXXXXXX - Xfer length min=1024 max=124928 average=95868 done Rewriting... XXXXXXXXXX - Xfer length min=1024 max=124928 average=33426 done Writing intelligently... XXXXXXXXXX - Xfer length min=1024 max=124928 average=112278 done Reading with getc()... XXXXXXXXXX - Xfer length min=1024 max=36864 average=31538 done Reading intelligently... XXXXXXXXXX - Xfer length min=1024 max=36864 average=28550 done
-------Sequential Output-------- ---Sequential Input-- --Random-- -Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks--- Machine MB K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU 1.3.85 200 3015 89.3 3308 36.8 1256 24.5 2383 87.0 3597 28.3 1.3.84+P 200 3044 90.8 3491 39.0 1549 30.4 2855 88.8 3867 30.0
1.3.85 : linux 1.3.85 with Linus's interpretation of asynchronous read-ahead. 1.3.84+P : linux 1.3.84 with my patch for asynchronous read-ahead.
What is wrong with 1.3.85: - CPU load for getc() (1k Read) - Average Xfer length with getc() - Speed for getc() - Rewrite - Average Xfer length for read block (8k) - Speed for read block
Here is the patch against linux-1.3.84 I used for this test: ------------------------------------------------------------ The previous one gives about the same performances. I invite you to try one of those patches.
---------------------------------- CUT HERE ------------------------------- --- linux/mm/filemap.c.00 Fri Apr 5 23:00:30 1996 +++ linux/mm/filemap.c Mon Apr 8 20:37:48 1996 @@ -296,10 +296,14 @@ * of the logic when it comes to error handling etc. */ #define MAX_READAHEAD (PAGE_SIZE*8) +#define MIN_READAHEAD (PAGE_SIZE) int generic_file_read(struct inode * inode, struct file * filp, char * buf, int count) { int error, read; unsigned long pos, page_cache; +#ifndef ONLY_SYNCHRONOUS_READ_AHEAD + int try_async; +#endif if (count <= 0) return 0; @@ -308,6 +312,41 @@ page_cache = 0; pos = filp->f_pos; +#ifndef ONLY_SYNCHRONOUS_READ_AHEAD + /* + * Dont beleive f_reada + */ + if (pos <= filp->f_rapos && pos + filp->f_ralen >= filp->f_rapos) { + filp->f_reada = 1; + } + else if (pos+count < MIN_READAHEAD || !filp->f_rapos || + pos > filp->f_rapos) { + filp->f_reada = 0; + } + + if (filp->f_reada) { + try_async = 1; + filp->f_ramax += filp->f_ramax; + } + else { + try_async = 0; + filp->f_rapos = 0; + filp->f_ralen = 0; + filp->f_ramax = 0; + } + + /* + * Compute a good value for read-ahead max + */ + if (filp->f_ramax < count) + filp->f_ramax = count & PAGE_MASK; + + if (filp->f_ramax < MIN_READAHEAD) + filp->f_ramax = MIN_READAHEAD; + else if (filp->f_ramax > MAX_READAHEAD) + filp->f_ramax = MAX_READAHEAD; +#endif + for (;;) { struct page *page; unsigned long offset, addr, nr; @@ -350,6 +389,8 @@ if (nr > count) nr = count; +#ifdef ONLY_SYNCHRONOUS_READ_AHEAD +/* SYNCHRONOUS only read-ahead code */ /* * We may want to do read-ahead.. Do this only * if we're waiting for the current page to be @@ -373,6 +414,68 @@ __wait_on_page(page); } unlocked_page: +#else /* ASYNCHRONOUS read-ahead code */ +{ + unsigned long max_ahead, ahead; + unsigned long rapos, ppos; + + ppos = pos & PAGE_MASK; + + /* Do some synchronous read-ahead */ + if (page->locked) { + max_ahead = filp->f_ramax; + rapos = ppos; + } + /* Do some asynchronous read-ahead */ + else { + rapos = filp->f_rapos & PAGE_MASK; + if (rapos) rapos -= PAGE_SIZE; + + if (try_async == 1 && pos <= filp->f_rapos && + pos + filp->f_ralen >= filp->f_rapos) { + struct page *a_page; + + max_ahead = filp->f_ramax + PAGE_SIZE; + + if (rapos < inode->i_size) { + a_page = find_page(inode, rapos); + if (a_page) { + if (a_page->locked) + max_ahead = 0; + a_page->count--; + } + } + else + max_ahead = 0; + try_async = 2; + } + else { + max_ahead = 0; + } + } + + ahead = 0; + while (ahead < max_ahead) { + ahead += PAGE_SIZE; + page_cache = try_to_read_ahead(inode, rapos + ahead, page_cache); + } + + if (ahead > 0) { + filp->f_ralen = ahead; + /* Force unplug device in order to start asynchronous */ + if (try_async == 2) { + schedule(); + try_async = 1; + } + } + filp->f_rapos = rapos + ahead + PAGE_SIZE; + + if (page->locked) { + __wait_on_page(page); + } +} +#endif + if (!page->uptodate) goto read_page; if (nr > inode->i_size - pos) --- linux/include/linux/fs.h.00 Wed Mar 27 00:50:36 1996 +++ linux/include/linux/fs.h Sat Apr 6 13:32:53 1996 @@ -321,6 +321,12 @@ unsigned short f_flags; unsigned short f_count; off_t f_reada; + +/* Added for asynchronous read-ahead patch */ + loff_t f_rapos; /* Last read-ahead position */ + unsigned long f_ralen; /* Length of previous read-ahead */ + unsigned long f_ramax; /* Current max read-ahead (futur use) */ + struct file *f_next, *f_prev; int f_owner; /* pid or -pgrp where SIGIO should be sent */ struct inode * f_inode; ---------------------------------- CUT HERE ------------------------------- Best Regards, Gerard.
|  |