Hi, I Emailed this afternoon that bwlimit leads to a much too low bwlimit if small amounts of data are sent in each write. I wrote a small patch now. Congrats on the code: It's nice and clean: I wrote a working patch in 5 minutes after examining a total of 25 lines of code. (My backup used to require two hours of small sleeps alone, which should be reduced by a factor of 8....) Roger. P.S. I'm not on the list. -- ** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2600998 ** *-- BitWizard writes Linux device drivers for any device you may have! --* * The Worlds Ecosystem is a stable system. Stable systems may experience * * excursions from the stable situation. We are currently in such an * * excursion: The stable situation does not include humans. *************** -------------- next part -------------- diff -ur rsync-2.5.6.orig/io.c rsync-2.5.6/io.c --- rsync-2.5.6.orig/io.c Thu Apr 11 04:11:50 2002 +++ rsync-2.5.6/io.c Tue Jun 17 23:25:45 2003 @@ -416,10 +416,19 @@ * use a bit less bandwidth than specified, because it doesn't make up * for slow periods. But arguably this is a feature. In addition, we * ought to take the time used to write the data into account. + * + * During some phases of big transfers (file XXX is uptodate) this is + * called with a small bytes_written every time. As the kernel has to + * round small waits up to guarantee that we actually wait at least + * the requested number of microseconds, this can become grossly + * inaccurate. We therefore keep a cumulating number of microseconds + * to wait, and only actually perform the sleep when the rouding + * becomes insignificant. (less than 10%) -- REW. **/ static void sleep_for_bwlimit(int bytes_written) { struct timeval tv; + static int time_to_sleep = 0; if (!bwlimit) return; @@ -427,9 +436,12 @@ assert(bytes_written > 0); assert(bwlimit > 0); - tv.tv_usec = bytes_written * 1000 / bwlimit; - tv.tv_sec = tv.tv_usec / 1000000; - tv.tv_usec = tv.tv_usec % 1000000; + time_to_sleep += bytes_written * 1000 / bwlimit; + + if (time_to_sleep < 100000) return; + + tv.tv_sec = time_to_sleep / 1000000; + tv.tv_usec = time_to_sleep % 1000000; select(0, NULL, NULL, NULL, &tv); }