You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm using usb4java 1.2.0 with a full-speed USB device that I'm developing.
When using the low-level libusb API, I am able to achieve throughput speeds near the theoretical maximum for a full-speed bulk endpoint (1114.112 KB/s).
If I switch to the high-level javax.usb API, my throughput drops by an amount that appears to depend not just on the machine I'm using, but on the port I'm connected to. I always see performance penalties of at least 50%.
I've developed a simple benchmarking tool. The device side reads a 4-byte network-byte-order integer from an OUT endpoint, then transmits that many bytes of garbage on an IN endpoint.
The low-level and high-level usb4java benchmark code is inlined below.
On one port on my development machine, I get the following results:
org.usb4java API benchmark
Writing header
4 bytes sent
Reading 1048576 bytes
1048576 bytes received
1048576 bytes in 1021 ms, 1002.9382957884428 KB/s
javax.usb API benchmark
Writing header
4 bytes sent
Reading 1048576 bytes
1048576 bytes received
1048576 bytes in 2311 ms, 443.09822587624404 KB/s
On another port, I get these results:
org.usb4java API benchmark
Writing header
4 bytes sent
Reading 1048576 bytes
1048576 bytes received
1048576 bytes in 971 ms, 1054.5829042224511 KB/s
javax.usb API benchmark
Writing header
4 bytes sent
Reading 1048576 bytes
1048576 bytes received
1048576 bytes in 16538 ms, 61.91800701414923 KB/s
As you can see, the performance hit is 56% on one port, and 94%(!) on the other.
I have seen this performance penalty on Windows 7 64-bit and Ubuntu Linux 32-bit and 64-bit.
UsbBench.java:
importorg.usb4java.*;
importjava.nio.*;
importjava.io.*;
publicclassUsbBench
{
publicstaticfinalshortidVendor = (short)0x03eb;
publicstaticfinalshortidProduct = (short)0x2423;
publicstaticfinalbyteifaceId = (byte)0x00;
publicstaticfinalbyteoutEp = (byte)0x02;
publicstaticfinalbyteinEp = (byte)0x81;
publicstaticfinalinttimeout = 60000;
publicstaticvoidmain(Stringargs[])
throwsException
{
intresult;
DeviceHandlehandle;
intsize = Integer.parseInt(args[0]);
ByteArrayOutputStreamheaderStream = newByteArrayOutputStream();
DataOutputStreamout = newDataOutputStream(headerStream);
out.writeInt(size);
byte[] header = headerStream.toByteArray();
result = LibUsb.init(null);
if (result != LibUsb.SUCCESS) thrownewLibUsbException("Unable to initialize libusb.", result);
handle = findDevice(idVendor, idProduct);
if (handle == null) thrownewRuntimeException("Device not found");
try {
result = LibUsb.claimInterface(handle, ifaceId);
if (result != LibUsb.SUCCESS) thrownewLibUsbException("Unable to claim interface", result);
ByteBufferbuffer = ByteBuffer.allocateDirect(header.length);
buffer.put(header);
IntBuffertransfered = IntBuffer.allocate(1);
System.out.printf("Writing header\n");
result = LibUsb.bulkTransfer(handle, outEp, buffer, transfered, timeout);
if (result != LibUsb.SUCCESS) thrownewLibUsbException("Bulk transfer failed", result);
System.out.printf("%d bytes sent\n", transfered.get());
buffer = ByteBuffer.allocateDirect(size);
transfered = IntBuffer.allocate(1);
System.out.printf("Reading %d bytes\n", size);
longstart = System.currentTimeMillis();
result = LibUsb.bulkTransfer(handle, inEp, buffer, transfered, timeout);
longtime = System.currentTimeMillis() - start;
if (result != LibUsb.SUCCESS) thrownewLibUsbException("Bulk transfer failed", result);
intrx = transfered.get();
System.out.printf("%d bytes received\n", rx);
System.out.printf("%s bytes in %s ms, %s KB/s\n",
rx, time, (rx / (time / 1000.0)) / 1024.0);
}
finally
{
LibUsb.releaseInterface(handle, ifaceId);
LibUsb.close(handle);
LibUsb.exit(null);
}
}
privatestaticDeviceHandlefindDevice(shortvendorId, shortproductId)
{
// Read the USB device listDeviceListlist = newDeviceList();
intresult = LibUsb.getDeviceList(null, list);
if (result < 0) thrownewLibUsbException("Unable to get device list", result);
try
{
// Iterate over all devices and scan for the right onefor (Devicedevice: list)
{
DeviceDescriptordescriptor = newDeviceDescriptor();
result = LibUsb.getDeviceDescriptor(device, descriptor);
if (result != LibUsb.SUCCESS) thrownewLibUsbException("Unable to read device descriptor", result);
if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId)
{
DeviceHandlehandle = newDeviceHandle();
result = LibUsb.open(device, handle);
if (result != LibUsb.SUCCESS) thrownewLibUsbException("Unable to open USB device", result);
returnhandle;
}
}
}
finally
{
// Ensure the allocated device list is freedLibUsb.freeDeviceList(list, true);
}
// Device not foundreturnnull;
}
}
Most likely I misunderstood the JSR-80 spec and implemented the data transfer not ideally. Or maybe I did it correctly and the JSR-80 spec sucks... I'm open for pull requests here because of lack of time and know-how.
I'm using usb4java 1.2.0 with a full-speed USB device that I'm developing.
When using the low-level libusb API, I am able to achieve throughput speeds near the theoretical maximum for a full-speed bulk endpoint (1114.112 KB/s).
If I switch to the high-level javax.usb API, my throughput drops by an amount that appears to depend not just on the machine I'm using, but on the port I'm connected to. I always see performance penalties of at least 50%.
I've developed a simple benchmarking tool. The device side reads a 4-byte network-byte-order integer from an OUT endpoint, then transmits that many bytes of garbage on an IN endpoint.
The low-level and high-level usb4java benchmark code is inlined below.
On one port on my development machine, I get the following results:
On another port, I get these results:
As you can see, the performance hit is 56% on one port, and 94%(!) on the other.
I have seen this performance penalty on Windows 7 64-bit and Ubuntu Linux 32-bit and 64-bit.
UsbBench.java:
UsbBenchJavax:
The text was updated successfully, but these errors were encountered: