Closed mdxs closed 6 months ago
Thanks for looking into this. This is mainly a matter of looping and mathematical or bitwise operations being very slow/inefficent in Python, to the extent that using builtins that convert to strings end up being faster. Thus, there are unfortunately no easy ways to make this fast other than rewriting it in a compiled language like C (which I have no intention of doing since it would just make everything more difficult to set up and install).
While the ‘rbit24’ implementation is not particularly efficient, it’s readable as you say, and calls to it are few enough for it to not really matter. Originally the code was calling ‘rbit24’ multiple times for every single packet received, which I didn’t like and made me feel embarrassed about its inefficiency, so I changed it to calculate the CRC in a bit reversed form, and only perform a single ‘rbit24’ call when writing the packet to a PCAP file. This is “good enough” given the speed of modern computers and the data rate of Bluetooth LE; even an old PC from the 90s should be able to keep up without issue.
I’ll probably just leave ‘rbit24’ as is, since the speed up of your implementation is minor at the expense of making it less readable, and the function is now called infrequently enough for its inefficiency to be fine. Eventually this code will go away, as one of these days I plan to add support for receiving packets with invalid CRCs, and directly sending the CRC received over the air from the firmware to the host. Nonetheless, thanks for taking the time to investigate this and trying out different optimization strategies.
Agree with your assessment; and like the plan to include the CRC as seen over-the-air to the host (for #53).
I noticed in the commit history that https://github.com/nccgroup/Sniffle/commit/503e794362e8069ee6905b8eef64ced2ceecb0a0 introduced the file
python_cli/crc_ble.py
in which there is a utility functionrbit24()
to support reversing the bits in a 24 bit CRC.It has a comment/remark that it might not be the most efficient implementation: https://github.com/nccgroup/Sniffle/blob/5da809b960ab2d420b5280cb17ed9fd9ce5f6278/python_cli/sniffle/crc_ble.py#L41
However, I couldn't find any bitwise approaches that are faster. I tested for example:
But they turned out to be much slower.
While looking for alternative approaches, the following is (at least in my testing) consistently faster:
When tested with the following standalone script (using Python 3.10.12 in XUbuntu guest VM):
I get the following results:
Shows that the alternative
rbit24_alt()
function is slightly faster than the current approach.Note that the number of tests with asserts in the above is very limited, but hopefully this will help you in assessing the efficiency of the current approach (which IMO is already pretty good) and the alternative (which is slightly less readable, but a bit faster).