[sane-devel] USB throughput (Re: HP SJ5300C)

Sergey Vlasov vsu@altlinux.ru
Tue, 8 Apr 2003 16:37:33 +0400


On Mon, 7 Apr 2003 18:04:13 +0100
Major A <andras@users.sourceforge.net> wrote:

> 
> > At least with Mustek BearPaw 2400TA, there is a difference between using
> > scanner.c or libusb: libusb is slower.  Usually this does not matter -
> > but at some resolutions scanning becomes unusably slow with libusb (lots
> > of backtracking, even on Athlon XP 2000+), while the same settings with
> > /dev/usb/scanner0 gives at most 2-3 backtrackings.  This is because the
> > GT68xx chips have a very small buffer - only 16KB.
> > 
> > Looking at the code, I see that scanner.c uses 32KB buffer size for
> > read, but devio.c (which is used by libusb) uses one-page buffers (4KB
> > on x86).
> 
> Given that USB 1.1 has a maximum payload of 64 bytes per bulk packet,
> I don't see a problem with 16kB or even 4kB buffers. Are you sure this
> is what causes the slowdown?

With 4kB buffers, a scanline read will be split to several syscalls. 
Looks like this overhead is sufficient to cause the slowdown.

The full A4 scan at 600dpi (5100x7019) in 24 bit color mode takes up
about 3 minutes (the scan itself, not counting calibration;  however,
there is some backtracking even in Windows); the average transfer
speed is about 600 kB/s - about half of the theoretical USB 1.1
bandwidth. This mode is the most problematic (and 300dpi 24 bit color
also has some speed problems).

> > At least with Linux this can be improved - even beyond the scanner.c
> > capabilities.  usbdevfs has USBDEVFS_SUBMITURB, which allow asynchronous
> > URB submitting, and even seems to allow queueing more than one URB for
> > the same pipe.  (The Windows kernel driver for GT68xx seems to use this:
> > the usbsnoop logs shows that it submits 5 URBs at once and then receives
> > the scanned data using them as a buffer ring.)  However, this feature is
> > not currently supported by libusb.
> 
> Good that you mention this -- I'm using libusb for another project
> where throughput is really important. I'll have to look into the way
> libusb chains URBs.

libusb currently does not have any support for this - even in the
"1.0" CVS.

Also I don't know if the generic USB interfaces in other OSes (*BSD,
etc...) have such capabilities.