RD performance?
4nthraxx opened this issue · 4 comments
Hello @pylessard,
I implemented the software download using this lib (Vector interface, windows 10) but it looks like the Multi-message mechanism isn't terribly perfomant. Any insights here? I'm on a 500kbps bus and the download of 700kB of data takes ~ 40s? That's at least 3 times too slow.
Why is it that slow? Was anyone able to achieve faster transfer speeds? I'm pretty much just sending the multi message one after another with minimal downtime inbetween to grab new data from the bytearray.
Not sure I'm doing something wrong or is Windows impacting us so hard due to a ton of smaller timeouts in the transport layer...
Thanks in advance!
MK
Hi!
Yes, I see. My guess is that your server request a stmin and/or a blocksize greater than 0.
When that happens the stack will go to sleep when it needs to wait. Unfortunately, on Windows, the thread resolution is ~16ms and this implemntation runs in the user space. So if your server ask to wait 0.5ms between the messages, you may be unlucky and have 16ms between each message. Also, if the stack need to wait for a flow control message every 8 consecutive frames for example, then you may have the same unwanted delay.
Your options are :
- Configure your server to have blocksize=0 and also stmin=0.
- If you can't do the above, you can use the
suqash_stmin_requirement
parameter. Setting this to true will make the stack ignore the stmin requirement from the server and sends everything it can as fast as possible. This will avoid some user space delay and let the driver handle the transmission speed. - If the above aren't enough, you should consider using the Linux driver.
If your vendor has a ISO15765 DLL that can do better timing by talking directly to the driver, I am open to support it in this package.
In any case, I suggest you make a can log of your transmission and see what really goes on.
Regards
Thank you for your feedback!
A few findings that might help narrowing it down:
- squashing the stmin does nothing for me, getting very similar times with and without it even though my server does use these values
- the transmission times (delta between two CFs) are averaging around 0.24ms -> effectively 26.5kB/s vs. bus 62.5kB/s, but including the other frames, wating for the responses we transfer 252B in ~ 14ms so it goes down to ~ 16.8kB/s. I attached the CAN log snippet in case I'm missing something.
- Profiling the main sending loop shows we spend the a lot of time (if not most time) in queue related activities (empty/_qsize - see the attachment) - it might be a side-effect of removing all sleeps around the send/receive function... Attached the code as well, perhaps anyone finds something glaringly obvious there...
Hi,
Sorry for the delay. Here's what I think. I initially did not review your time calculation. You probably did : 700000*8/500000 = 11.2sec. A CAN frame has a lot of overhead. 112bits for 64 bits of data, this count in your bitrate.
With a 500kbps channel, you get 4 message per millisecond at best, so your 0.24ms delay shows that you are at full speed; this is good.
Then, IsoTP overhead chops a minimum 1 byte per CAN message, leaving 7 effective bytes per CAN message, yielding a rough maximum of 28bytes per millisecs assuming all of your data is inside a single IsoTP frame. This mean a best case scenario of ~ 700000/28000 = 25sec. (I am ignoring the Flow control frame in this calculation)
Now looking at your CAN log, I see that you send your data in chunk of 566 bytes. We are far from the ideal scenario of all the data into a single IsoTP frame. And looking at the timing, there's a 16ms delay in between your data chunk. This means that your software goes to sleep then you have to wait for Windows to wake it back up with its thread resolution of 16millisecs.
If we consider 16ms for each data block, we have 700000/566 * 0.016 = 19.8 sec.
25+19.8 sec = 44.8 sec, roughly what you get.
In other words, you are at full speed but have a total 19.8sec of sleep time. Best you can do is :
- Send bigger chunk of data
- Increase your bitrate
- Transmit over CAN FD to reduce the CAN and IsoTP overhead ratio
- Try to avoid your software going to sleep between each data block (not sure if this will be achievable honestly..)
Hope that helps.
This seems to be unavoidable under windows limitations.
As suggested the only way to increase performance was to send 64Byte frames with bit rate switch to whatever your max CAN FD speed may be.
Example settings for max speed for me:
self.bus = can.interface.Bus(bustype='vector', channel=0, bitrate=500000, app_name="CANoe", fd=True,
data_bitrate=2000000, bitrate_switch = True)
addr = isotp.Address(isotp.AddressingMode.Normal_11bits, rxid=0x104, txid=0x204, is_fd=True)
self.stack = isotp.CanStack(self.bus, address=addr, error_handler=self.my_error_handler,
params={'tx_padding': 0, 'can_fd': True,
'bitrate_switch': True,
'tx_data_length': 64,
'tx_data_min_length' : 8})